Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I would recommend the <a href="http://martinfowler.com/eaaCatalog/dataMapper.html" rel="nofollow noreferrer">Data Mapper pattern</a>. </p> <p><img src="https://i.stack.imgur.com/72aL0.gif" alt="enter image description here"></p> <p>Everything you said makes sense and this pattern fits. Your model should not know or care how it is persisted. Instead the mapper does what it suggests - maps your model to your database. One of the things I like about this approach is it encourages people to think about the model in terms of an object, not a relational database table, as often happens with active record patterns and table row gateways.</p> <p>Your object, unless very simple, typically will not reflect the structure of a database table. This lets you write good objects and then worry about the persistence aspects afterward. Sometimes more manual in that your mapper will need to deal with the complex joins, probably requiring writing some code or SQL, but the end result is it does just what you want and nothing more. No magic or conventions required if you don't want to leverage them.</p> <p>I've always though these articles do a good job of explaining some of the design patterns that can be used well in ZF: <a href="http://survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors#zfbook.implementing.the.domain.model.entries.and.authors.exploring.the.entry.data.mapper" rel="nofollow noreferrer">http://survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors#zfbook.implementing.the.domain.model.entries.and.authors.exploring.the.entry.data.mapper</a></p> <p><strong>UPDATE:</strong></p> <p>Well you mapper might extend from an interface similar to this:</p> <pre><code>&lt;?php interface Mapper_Interface { /** * Sets the name of the entity object used by the mapper. */ public function setObjectClass($class); /** * Sets the name of the list class used by the mapper. */ public function setObjectListClass($listClass); /** * Get the name of the object class used by the mapper. * */ public function getObjectClass(); /** * Get the name of the object list class used by the mapper. * * @return string */ public function getObjectListClass(); /** * Fetch one row. * * @param array $where Criteria for the selection. * @param array [$order = array()] Optionally the order of results * @return Object_Abstract * @throws Mapper_Exception */ public function fetchRow($where, $order = array()); /** * Fetch all records. If there is no underlying change in the persisted data this should * return a consistant result. * * @param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object. * @param string|array $order OPTIONAL An SQL ORDER clause. * @param int $count OPTIONAL An SQL LIMIT count. * @param int $offset OPTIONAL An SQL LIMIT offset. * @return Object_List_Abstract * @throws Mapper_Exception */ public function fetchAll($where = null, $order = null, $count = null, $offset = null); /** * Deletes one or more object. * * @param array|string $where Criteria for row deletion. * @return integer $affectedRows * @throws Mapper_Exception */ public function delete($where); /** * Saves a record. Either updates or inserts, as required. * * @param $object Object_Abstract * @return integer $lastInsertId * @throws Mapper_Exception */ public function save($object); } </code></pre> <p>And you would interact with the mapper like:</p> <pre><code>$fooObjectMapper = new Foo_Mapper; $fooObjectList = $fooObjectMapper-&gt;fetchAll(); var_dump($fooObjectList-&gt;first()); </code></pre> <p>or</p> <pre><code>$fooObjectMapper = new Foo_Mapper; $fooObject = $fooObject-&gt;fetch(array('id = ?' =&gt; 1)); $fooObject-&gt;setActive(false); $fooObjectMapper-&gt;save($fooObject); </code></pre> <p>I usually write a mapper abstract for any 'PDO' enabled databases. One of the attributes of that concrete mapper is then the Zend_Db_Adapter to issue commands against. Makes for a flexible solution, easy to use mock data sources in testing. </p>
 

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