Jump to:

3432 Posts in 1058 Topics by 734 members

Data Model Questions

SilverStripe Forums » Data Model Questions » Looping many to many in the controller

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1
Go to End
Author Topic: 473 Views
  • 3geeks
    Avatar
    Community Member
    9 Posts

    Looping many to many in the controller Link to this post

    Hi guys,

    I'm sure this is a very simple task but I'm just not sure on the syntax.

    Basically I have a Job dataobject that has the usual fields like Title, Description, etc, but it also has a many to many relationship with Locations as each job can have multiple locations assigned.

    So Job is (some code stripped out for clarity):

    class Job extends DataObject {
       static $db = array(
          'JobID' => "Int",
          'Title' => "Varchar(255)",
          'ShortDescription' => "Text",
          'Description' => 'HTMLText'
       );   

       public static $many_many = array(
          'Categories' => 'Category',
          'SubCategories' => 'SubCategory',
          'Locations' => 'Location',
          'JobTypes' => 'JobType'
       );
       
    public function getLongTitle() {
    $data = $this->Title . '  |  ';

    return $data;
    }
          
    }

    And location is (again missing code for clarity):

    class Location extends DataObject {
       static $db = array(
          'Title' => "Varchar(255)"
       );
       
       public static $many_many = array(
          'Jobs' => 'Job'
       );   
    }

    In my template I have a small block that shows the latest 5 jobs using this bit of code in the pages class.

       function LatestVacancies() {
          return DataObject::get('Job','','ID DESC','','5');   
       }


    Which is fine when I was only showing the title.

    What I need to do now however is show the locations after the job title. I know I could use another control block in the template to loop through the locations, but I only have a limited width of space so I want to use the ".LimitCharacters(35)".

    So what I want to do is return a long title from the php to the template which will be a single string in the format <job title> | <location1>, <location2>, etc...

    This way I will be able to use the LimitCharacters on that entire string as some job title's are really short the 35 character cut off will be part way through one of the locations, and some are long so it cuts off part way through the job title.

    So I might end up with:
    Assessor | Perth, Sydney
    Senior Quality Controller | Sydn ...
    Group Facilities and Capital Works ...
    etc.

    I started to make a getLongTitle() function in the Job DataObject which works fine (as I use other bits from the Job DataObject in the template) but I just don't know how to access the Locations array from the job and build that string.

    Like I said, this should be easy, I'm just not used to PHP or Silver Stripe.

    Hopefully someone can fix that one function up for me!

    Cheers,
    Duncan

  • 3geeks
    Avatar
    Community Member
    9 Posts

    Re: Looping many to many in the controller Link to this post

    Anyone?

    I would have thought this was about 2 lines of code... I just don't have any of my developers available to help me as I have them all on different projects so I'm trying to do this bit myself.

    Please help!

  • Izeroy
    Avatar
    Community Member
    3 Posts

    Re: Looping many to many in the controller Link to this post

    Hello,
    firstly you must used in Job Class or in Location Class for a many_many relationship the array

    $belongs_many_many = array();

    And then you can use in your template

    <% control LatestVacancies %>
    <% if Locations %>
    <% control Locations %>
    $LongTitle
    <% end_control %>
    <% end_if %>
    <% end_control %>

    This is only theory and i have not try this ;)

    Greetz
    Izeroy

  • Willr
    Avatar
    Forum Moderator
    5490 Posts

    Re: Looping many to many in the controller Link to this post

    As mentioned in the original post, should be in PHP

    public function getLongTitle() {
    $title = $this->Title . implode(", ", $this->Locations()->column('Title'));

    return substr($title, 0, 50);
    }

    The implode trick should work, if not you can do the longer - foreach($this->Locations() as $location) .... and append the locations there.

    The other thing I would do is add LongTitle to your $casting array to ensure the field is escaped in templates (http://doc.silverstripe.com/framework/en/topics/data-types#casting-arbitrary-values)

  • 3geeks
    Avatar
    Community Member
    9 Posts

    Re: Looping many to many in the controller Link to this post

    Thanks Willr.

    That was more what I was after. I was sure I could do it with a foreach loop I just wasn't sure on the syntax.

    I'll give the implode trick a bash first.

    Cheers.

    473 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.