Creating nested relationships with an ORM and minimizing queries Creating nested relationships with an ORM and minimizing queries codeigniter codeigniter

Creating nested relationships with an ORM and minimizing queries


First of all, I'm sorry to break this to you , but CodeIgniter's DataMapper is actually a variation of ActiveRecord pattern.

If you care, you compare the real DataMapper pattern with its counterpart - ActiveRecord. In short - difference is in fact that in DM pattern you Domain Object is unaware of type ( and even the existence ) of storage. It is used in manner like $mapper->store( $user );.

"Favor object composition over class inheritance." © GoF

That said..


If i read the examples right then it should work like this:( i am assuming that relationships between 'entities' are already established )

class Project extends DataMapper{   // --- the rest of your stuff    public function get_all_points()   {      $points = array();      $slides = $this->slide->get()->all;      foreach ( $slides as $slide )      {         $shapes = $slide->shape->get()->all;         foreach ( $shapes as $shape )         {            $points = array_merge( $point = $shape->point->get();         }      }      return $points;   }}

Then you can use something like

$project = new Project;$all_points = $project->where( 'id' , 1 )->get_all_points();foreach ( $all_points as $point ){   $point->x = 0;   $point->save();}

This should gather all th points that are related to project with ID 1, and set the X value to 0 and store each in the database .. not that any sane person would do it.



I am not using any sort of ORM, that's why i really hope i got this wrong, because this looks to me like an abomination.


I'm not sure how Datamapper does it but I have a custom GenericObject model for Codeigniter that does ORM like this:

class Article extends GenericObject{    public $relationships = array ( "has_many" => array ("comments"), "has_one" => array ("users") );}class Comments extends GenericObject{    public $relationships = array ( "belongs_to" => array ("articles", "users"), "has_one" => array ("users") );}class Users extends GenericObject{    public $relationships = array ( "has_many" => array ("comments", "articles") );}

If I want to get everything from a User then I can just do something like:

$User = new User( $some_user_id );$User->boot_relations("all");foreach ($User->Comments as $Comment){    echo $Comment->title."<br />";    echo $Comment->body."<br />";    echo "written by ".$User->username;}

So it can be fairly elegant (or at least I like to think so).


With most relational data, I typically lazy-load objects at they are needed. I'm not a PHP developer, but here's what I would do in pseudo-code.

class Projects {    var slides = null;    function getSlides() {        if(slides == null) {            slides = getSlidesForProject(this.id);        }        return slides;    }}class Slides {    var shapes = null;    function getShapes() {        if(shapes == null) {            shapes = getShapesForSlide(this.id);        }        return slides;    }}class Shapes {    //... same as Projects.getSlides and Slides.getShapes}

Unfortunately, this causes multiple calls to the database if you needed to get all Points for a Project.

With any MVC solution, I recommend going with a light Controller and a heavy Model to make code reuse and testing easier.