Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First it looks like you need to make a little bit more of a conceptual leap. With the data mapper pattern it helps to think in terms of objects instead of database tables. I found these two articles helpful when I needed to make the leap.</p> <p><a href="http://phpmaster.com/building-a-domain-model/" rel="nofollow">http://phpmaster.com/building-a-domain-model/</a><br /> <a href="http://phpmaster.com/integrating-the-data-mappers/" rel="nofollow">http://phpmaster.com/integrating-the-data-mappers/</a></p> <p>That being said ZF 1 has some very useful tools for building a data mapper/domain model.</p> <p>The convention in ZF 1 is for each table you are working with to be accessible through the Zend_Db_Table api. The simplest way I've found is to just use the <a href="http://framework.zend.com/manual/1.12/en/zend.db.table.html#zend.db.table.defining" rel="nofollow">DbTable resource</a> for each table. You could also use the <code>Zend_Db::factory</code> or <code>new Zend_Db_Table('tableName')</code> or any other method that appeals to you.</p> <p>This example is based on a mp3 song track.</p> <pre><code>//in effect this is the database adapter for database table 'track', This is $tableGateway used later. &lt;?php class Application_Model_DbTable_Track extends Zend_Db_Table_Abstract { //name of database table, required to be set if name of class does not match name of table protected $_name = 'track'; //optional, column name of primary key protected $_primary = 'id'; } </code></pre> <p>there are several ways to attach a table to the Db adapter and the Zend_Db_Table api, I just find this method simple to implement and it makes setting up a mapper simple as well.</p> <p>The mapper class is the bridge between the data source and your object (domain entity). The mapper interacts with the api for Zend_Db_Table in this example.</p> <p><strong>A really important point to understand:</strong> when using classes that extend Zend_Db_Table_Abstract you have all the basic functionality of the Zend_Db component at your disposal. (find(),fetchall(), fetchRow(), select() ...)</p> <pre><code>&lt;?php class Music_Model_Mapper_Track extends Model_Mapper_Abstract { //the mapper to access the songs artist object protected $artistMapper; //the mapper to access to songs album object protected $albumMapper; /** * accepts instance of Zend_Db_Table_Abstract * * @param Zend_Db_Table_Abstract $tableGateway */ public function __construct(Zend_Db_Table_Abstract $tableGateway = null) { //at this point I tend to hardcode $tablegateway but I don't have to $tableGateway = new Application_Model_DbTable_Track(); parent::__construct($tableGateway); //parent sets the $tablegateway variable and provides an abstract requirement //for createEntity(), which is the point of this class } /** * Creates concrete object of Music_Model_Track * * @param object $row * @return Music_Model_Track */ public function createEntity($row) { $data = array( 'id' =&gt; $row-&gt;id, 'filename' =&gt; $row-&gt;filename, 'format' =&gt; $row-&gt;format, 'genre' =&gt; $row-&gt;genre, 'hash' =&gt; $row-&gt;hash, 'path' =&gt; $row-&gt;path, 'playtime' =&gt; $row-&gt;playtime, 'title' =&gt; $row-&gt;title, 'track_number' =&gt; $row-&gt;track_number, 'album' =&gt; $row-&gt;album_id,//foriegn key 'artist' =&gt; $row-&gt;artist_id//foriegn key ); //instantiate new entity object return new Music_Model_Track($data); } /** * findById() is proxy for find() method and returns * an entity object. * * @param type $id * @return object Model_Entity_Abstract */ public function findById($id) { //instantiate the Zend_Db_Select object $select = $this-&gt;getGateway()-&gt;select(); $select-&gt;where('id = ?', $id); //retrieve one database table row $row = $this-&gt;getGateway()-&gt;fetchRow($select); //create one entity object Music_Model_Track $entity = $this-&gt;createEntity($row); //return one entity object Music_Model_Track return $entity; } //truncated } </code></pre> <p>All that has gone before is for the express purpose of building the following object:</p> <pre><code>&lt;?php class Music_Model_Track extends Model_Entity_Abstract { /** * $id, __set, __get and toArray() are implemented in the parent */ protected $album; protected $artist; protected $filename; protected $format; protected $genre; protected $hash; protected $path; protected $playtime; protected $title; protected $track_number; //artist and album mappers protected $albumMapper = null; protected $artistMapper = null; //these are the important accessors/mutators because they convert a foreign key //in the database table to an entity object. public function getAlbum() { //if the album object is already set, use it. if(!is_null($this-&gt;album) &amp;&amp; $this-&gt;album instanceof Music_Model_Album) { return $this-&gt;album; } else { //else we make a new album object if(!$this-&gt;albumMapper) { $this-&gt;albumMapper = new Music_Model_Mapper_Album(); } //This is the album object we get from the id in our reference array. return $this-&gt;albumMapper-&gt;findById($this-&gt;getReferenceId('album')); } } //same as above only with the artist object. public function getArtist() { if(!is_null($this-&gt;artist) &amp;&amp; $this-&gt;artist instanceof Music_Model_Artist) { return $this-&gt;artist; } else { if(!$this-&gt;artistMapper) { $this-&gt;artistMapper = new Music_Model_Mapper_Artist(); } return $this-&gt;artistMapper-&gt;findById($this-&gt;getReferenceId('artist')); } } //the setters record the foriegn keys recorded in the table row to an array, //this allows the album and artist objects to be loaded only when needed. public function setAlbum($album) { $this-&gt;setReferenceId('album', $album); return $this; } public function setArtist($artist) { $this-&gt;setReferenceId('artist', $artist); return $this; } //standard setter and getters truncated... } so when using the track object you would get album or artist info like: //this would be used in a controller most likely. $mapper = new Music_Model_Mapper_Track(); $track = $mapper-&gt;findById('1'); //all of the information contained in the album or artist object is //available to the track object. //echo album title, year or artist. This album object also contains the artist object //so the artist object would be available in two ways. echo $track-&gt;album-&gt;title; //or echo $track-&gt;artist-&gt;name; echo $track-&gt;album-&gt;artist-&gt;name; echo $track-&gt;getAlbum()-&gt;getArtist()-&gt;getName(); </code></pre> <p>So what you really need to decide is how you want to structure your application. What I see as obvious may not be an option you wish to implement. A lot of the answers to your questions depend on exactly how these resources are to be used.</p> <p>I hope this helps you at least a little bit.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload