0

I have class that representing model of user with foreign key with is id of picture .

class Model_User extends Model_AbstractEntity
{
    protected $u_id;
    protected $u_email;
    protected $u_firstname;
    protected $u_lastname;
    protected $u_password;
    protected $u_salt;
    protected $u_created_at;
    protected $u_updated_at;
    protected $u_fb;
    protected $u_status;
    protected $u_r_id;
    protected $u_p_id;
}

Class with is responsible for picture model look like this:

class Model_Picture extends Model_AbstractEntity
{
    protected $p_id;
    protected $p_created_at;
    protected $p_updated_at;
    protected $p_caption;
    protected $p_name;
    protected $p_basePath;
    protected $p_available;
    protected $p_u_id;
}

This is only model part with is getting data from database. Foreing key is u_p_id and key in picture is p_id My problem is that when doing select() by Zend db table it returning me data with foreign key but how can I know which part of return data is picture part to set the proper picture model.... how to do it in proper way no to do 2 queries one for user and second for picture to create 2 associative objects. I'm talking now about relation ont to one but maybe will be one to many..

MarJano
  • 1,257
  • 2
  • 18
  • 39

1 Answers1

1

Typically your entity models will not exist in void they will exist in concert with some type of Data Mapper Model. The Mapper will typically be charged with gathering the data from whatever source is handy and then constructing the entity model.

For example I have a music collection that has an album entity:

<?php
class Music_Model_Album extends Model_Entity_Abstract implements Interface_Album
{
    //id is supplied by Entity_Abstract
    protected $name;
    protected $art;
    protected $year;
    protected $artist; //alias of artist_id in Database Table, foreign key
    protected $artistMapper = null;

    /**
     * Constructor, copied from Entity_Abstract
     */
    //constructor is called in mapper to instantiate this model
    public function __construct(array $options = null)
    {         
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

  /**
   * Truncated for brevity.
   * Doc blocks and normal getters and setters removed
   */


    public function getArtist() {
        //if $this->artist is set return
        if (!is_null($this->artist) && $this->artist instanceof Music_Model_Artist) {
            return $this->artist;
        } else {
            //set artist mapper if needed
            if (!$this->artistMapper) {
                $this->artistMapper = new Music_Model_Mapper_Artist();
            }
            //query the mapper for the artist table and get the artist entity model
            return $this->artistMapper->findById($this->getReferenceId('artist'));
        }
    }
    //set the artist id in the identity map
    public function setArtist($artist) {
        //artist id is sent to identity map. Can be called later if needed - lazy load
        $this->setReferenceId('artist', $artist);
        return $this;
    }


    //each album will have multiple tracks, this method allows retrieval as required.
    public function getTracks() {
        //query mapper for music track table to get tracks from this album
        $mapper = new Music_Model_Mapper_Track();
        $tracks = $mapper->findByColumn('album_id', $this->id, 'track ASC');

        return $tracks;
    }
}

In the mapper I would build the entity model like:

 //excerpt from Model_Mapper_Album
 //createEntity() is declared abstract in Model_Mapper_Abstract
 public function createEntity($row)
    {
        $data = array(
            'id'     => $row->id,
            'name'   => $row->name,
            'art'    => $row->art,
            'year'   => $row->year,
            'artist' => $row->artist_id,//
        );

        return new Music_Model_Album($data);
    }

to use this method in a mapper method, might look like:

 //this is actually from Model_Mapper_Abstract, b ut give the correct idea and will work in any of my mappers.
 //this returns one and only one entity
 public function findById($id)
    {
        //if entity id exists in the identity map
        if ($this->getMap($id)) {
            return $this->getMap($id);
        }
        //create select object
        $select = $this->getGateway()->select();
        $select->where('id = ?', $id);
        //fetch the data
        $row = $this->getGateway()->fetchRow($select);
        //create the entity object
        $entity = $this->createEntity($row);
        //put it in the map, just in case we need it again
        $this->setMap($row->id, $entity);
        // return the entity
        return $entity;
    }

I have seen Entities and Mappers built in many different ways, find the method that you like and have fun.

A lot of code has been left out of this demonstration as it doesn't really apply to the question. If you need to see the complete code see it at GitHub.

RockyFord
  • 8,529
  • 1
  • 15
  • 21
  • In you example you have to ask 2 times . $mapper = new Music_Model_Mapper_Track(); $tracks = $mapper->findByColumn('album_id', $this->id, 'track ASC'); So I want to ommit asking 2 only one time DB with join query – MarJano Nov 08 '12 at 19:55
  • I do it that in this example because I rarely need that particular data set. So it is set up to be available if needed. However if you need the data in your entity available all the time build a join. The info will also be avialble if I use something like `$result->album->artist` so the info is always available, it just lazy loads. – RockyFord Nov 09 '12 at 09:10
  • `$mapper = new Music_Model_Mapper_Track();` this is the database adapter (my connection to mysql).`$mapper->findByColumn('album_id', $this->id, 'track ASC');` this is the database query. This is an aliased `fetchRow()` method that returns an entity object. – RockyFord Nov 09 '12 at 09:17
  • if you are performing queries in your entity models, your data structure could probably use some refactoring. – RockyFord Nov 09 '12 at 09:19