Jump to content

Designing DataMapper for objects that sometimes need to aggregate other objects


Recommended Posts

I have an object called student which maps to a student table. There is also a courses table, and user_courses table to assign students to courses. This student object can have many course objects, and therefore, with my Students DataMapper it will retrieve student objects and any course objects for the courses that the student is enrolled in. This works fine for the cases where I need all of this information, but in the cases where I only need to display the student name and last name, the retrieval of course objects is unnecessary. My question is, how should I design my dataMappers to account for this? Should I have separate mappers for different levels of student objects, i.e. baseStudentObject with just the basic student info and then an extendedStudentObject which additionally includes the course objects? Or better to implement some sort of lazy loading solution? As always, all input is very much appreciated! Cheers.

 

Thx for your reply, Ignace.  If there are also specific instances where you know you will need to load all of the child objects, should there be some sort of flag set indicating that all the child objects should be loaded?  Or is this potential performance hit a cost of the lazy load pattern??

Lazy Loading is as simple as:

 

public function getFoo() {
    if(is_null($this->foo)) {
        $this->foo = $this->_getFoo();
    }
    return $this->foo;
}

 

This way you will load Foo objects when you actually need them (when you call upon them)

Lazy Loading is as simple as:

 

public function getFoo() {
    if(is_null($this->foo)) {
        $this->foo = $this->_getFoo();
    }
    return $this->foo;
}

 

This way you will load Foo objects when you actually need them (when you call upon them)

 

That is Lazy Init. Lazy Loading includes Lazy Initalization, Virtual Proxy (my personal favorite) and Value Holder.

 

This a vproxy btw:

class Meh {
   public function foo(){}
}
class MehProxy extends Meh {
   private $_subject;
   public function foo(){
       if(!$this->_subject){
             $this->_subject = $this->_getSubject(); //From wherever
       }
       return $this->_subject->foo();
  }
}

Appreciate the input guys!  My followup question is that if you know that you will need to load all child objects in a specific situation, is there a way to load them all at once, rather than have them automatically set to lazy load, and therefore instead of x amounts of queries to the db, it would just be 1 for this scenario?

Wouldn't that mean that if I had 10 Parent Objects with 1 Child Object each, it would lead to 10 read's to the DB for the child objects, instead of somehow setting it up to have just 1 read to obtain all the child objects?

Yes, if each parent object was a stand-alone class. But you can create a class that holds all parent objects and upon retrieving a parent from the object it would load all applicable child objects and populate the parent object.

 

class FooRepository {
    public function getBar($i, $loadChildren = true) {
        if(!array_key_exists($i, $this->bar)) {
            $this->bar[$i] = $this->_loadBar($i, $loadChildren);
        }
        if($loadChildren && !$this->bar[$i]->hasChildren() && $this->bar[$i]->hasFuckBuddy()) { // Found that in "God's Stuff/Earth/mating.source" 
            $this->bar[$i]->setChildren($this->_getChildren($i));
        }
        return $this->bar[$i];
    }
}

With Virtual Proxy the object is a transparent replacement for the actual object. So you issue a query to the database, if the resulting data contains the data needed to fully load the related object, you just construct and set the normal object.

 

If you did not load the related data (but did for example load a foreign key so you can load later), you set the vproxy instead. Client code is completely unaware of the difference: they cannot tell the diff between a "Meh" and a "MehProxy".

 

This solution is far superior for the purpose of ORM to other lazy init solutions.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.