Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

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

Multiple levels of getManyManyComponents


Reply


7 Posts   776 Views

Avatar
dendeffe

Community Member, 135 Posts

26 May 2011 at 4:07am

How can I do a getManyManyComponents for each DO in a DataObjectSet and bundle the result in one DataObjectSet?

Something like $this->getManyManyComponents('DOType1')->getManyManyComponents('DOType1');

I can do it by looping through the first set with a for each loop, but is there an easier way?

Avatar
swaiba

Forum Moderator, 1804 Posts

26 May 2011 at 4:23am

Edited: 26/05/2011 6:45am

how about a recursive function... I've started with some function that might help, but I'm lost as to wehter it;ll work and what the result you are after is...

function GetRecursiveAllObjects($obj,$strRelationshipName) {
while ($obj->hasMethod($strRelationshipName)) {
$dos->merge($obj->$strRelationshipName);
$obj = ?;
$this->GetRecursiveAllObjects($obj,$strRelationshipName);
}
}

edit updated the function a little

Avatar
dendeffe

Community Member, 135 Posts

26 May 2011 at 7:22pm

I'm not sure if that is cleaner/more efficient then what I'm doing at the moment. This is what I have:

   function Recipients()
   {
      $emailsOnList = array();
      $myLists = $this->DefNewsletterSubscriberLists();
      $myLists = $myLists->items;
      // loop through mailing lists
      for($x = 0; $x < count($myLists); $x++)
      {
         $myEmails = $myLists[$x]->getManyManyComponents('DefNewsletterSubscribers');
         $myEmails = $myEmails->items;
         // loop emails
         for($y = 0; $y < count($myEmails); $y++) {
            $emailsOnList[] = $myEmails[$y]->Email;
         }
      }
   
      $emailsOnList = array_unique($emailsOnList);
      return $emailsOnList;
   }

I'll probably look into returning a DataObjectSet instead of an Array. Was hoping to do something more DataObject-like instead of the for loop.
I'm also concerned if this is good performance-wise.

Avatar
MarcusDalgren

Community Member, 288 Posts

26 May 2011 at 8:30pm

Performance wise you're better off looping through arrays like you're doing than traversing dataobjectsets. Arrays are generally much faster than object iterators. I've also read that recursive functions are slow in PHP but I don't have anything to back that up with so don't take my word for it.

Avatar
swaiba

Forum Moderator, 1804 Posts

26 May 2011 at 8:39pm

you know, I thought it you wanted it to keep going recursively...

As I understand it (although I could be badly wrong here) doing a foreach on a dataobjectset invokes it's ->toArray() method and then it iterates over that... besides I optimize when it's required in the 1% of cases in the 99% I prefer succinct readable code.

Avatar
MarcusDalgren

Community Member, 288 Posts

26 May 2011 at 8:52pm

I agree with you Swaiba on performance vs readability but I do want to add that (at least for me) recursive functions are seldom readable in an easy fashion. Your function is very short so that one's easy to read but at least in my experience recursive functions often get messy pretty fast. The reason I wrote about performance was simply because Dendeffe asked about it.

For the foreach I think it's using the iterator interface defined in the class and thus each foreach calls one of those methods. Those methods do work directly with the internal array but I do think you still get the overhead of calling the object methods. But like Swaiba said in 99% of the cases this shouldn't be the overhead in your application so it isn't really something to worry about unless you're working with huge data sets.

Avatar
swaiba

Forum Moderator, 1804 Posts

26 May 2011 at 9:06pm

You know I haven't written a recursive function for years and then yesterday I wrote 2... hopefully it'll be years before I do again!