Hi Matthew

I suggest to convert the Mapper's methods to static methods. The table could
be a static property of mapper's class.

I don't understand why i would need to instantiate a Mapper class as there
is no state in that object, i think it's enough to call his static methods:

$p = PeopleMapper::getById(1); // returns a People object
$rp = PeopleMapper::getNewPeople(); // returns an array of People objects
PeopleMapper::save($p); // saves a People object
Etc....

-----Mensaje original-----
De: Matthew Weier O'Phinney [mailto:[email protected]] 
Enviado el: viernes, 08 de mayo de 2009 20:35
Para: [email protected]
Asunto: Re: [fw-general] Zend Model and quickstart

-- remataklan <[email protected]> wrote (on Friday, 08 May 2009, 05:36 AM
-0700):
> I was trying to understand the quickstart guide on the ZF site. 
> 
> My question is about the model part.
> First of all a little check to see if I understand the stuff. As I 
> understand Zend_Db_Table handles the stuff with database. The mapper 
> maps this to the model and the model handles everything about getting 
> and setting data. Is this correct?

That's how we setup the quick start, yes. It's using three patterns:

 * Domain Model (the Default_Model_Guestbook class)
 * Data Mapper (the Default_Model_GuestbookMapper class)
 * Table Data Gateway (the Default_Model_DbTable_Guestbook class)

One slight difference to what you wrote: the domain model is an object that
has properties and behavior. The data mapper maps those to a persistence
layer (the database, in this case).

> Now the question, is it me or in the end the data we passed to the 
> view is a little bit large. I mean the whole model object is passed to 
> the final view.  Is this the correct way to do it?

It's one way to do it. When it comes down to it, the size of an item passed
to the view is not really an issue -- and, in fact, passing objects is
typically less expensive than other data as the objects are passed by
reference.

> And finally if I wanted to find to all posts from a certain user do I 
> need a new function in the mapper? Something like

So, another person responded already, and he was suggesting using
Zend_Db_Table as your model.

This is a perfectly valid approach -- Martin Fowler notes in his section on
Domain Models that it's often expedient to use ActiveRecord or table data
gateway directly as your models, particularly for prototyping or when the
model has a basically 1:1 mapping to the database. 

Problems arise, however, when you decide you want to persist your data
differently. For instance, if you decide to move to a document storage
system, or offload the direct data access to a middle-ware tier accessed via
web services, or even want to abstract access so that you can use memcached
unless the data is not cached. It was for these reasons that we chose to go
with a slightly more abstract approach in the current iteration of the Quick
Start.

So, back to your example; that's one way to do it. The drawback is you'll
find yourself writing methods in your mapper for every behaviour in your
model, which quickly eliminates some of the benefits of having a data mapper
in the first place.

Another approach is to build and use a Query Object
(http://www.martinfowler.com/eaaCatalog/queryObject.html), and then have the
data mapper figure out how to map the query object into a request for the
data access layer. In such a case, you might do something like
this:

    public function query(Model_QueryObject $query)
    {
        $table  = $this->getDbTable();
        $select = $table->select();

        foreach ($query->getCriteria() as $criteria) {
            $method = 'where';
            if ($criteria->isOr()) {
                $method = 'orWhere';
            }
            $statement = $criteria->getField() . ' '
                       . $criteria->getOperator() . ' ?';
            $select->$method($statement, $criteria->getValue());
        }

        $resultSet = $table->fetchAll($select);
        $entries   = array();
        foreach ($resultSet as $row) {
            $entry = new Model_List($row->toArray());
            $entry->setMapper($this);
            $entries[] = $entry;
        }
        return $entries;
    }

This affords you the ability to have a fairly generic data mapper that can
handle arbitrary criteria. It's not quite as flexible as Zend_Db_Select (no
support for joins, order, having, etc.), but for most purposes it would be
adequate.

Your model, then, would have a postsByUser() method, and would look
something like this:

    public function postsByUser($userId)
    {
        $query = new Model_QueryObject();
        $query->addCriteria(array(
            'field'    => 'user_id', 
            'operator' => '=',
            'value'    => $userId,
        ));
        return $this->getMapper()->query($query);
    }

I won't go into the query object definition for now -- but it's basically
just able to add criteria objects and return them. The criteria objects
themselves simply are value objects, with properties for field, operator,
and value.

> public function postsByUser($userId)
>     {
>         $resultSet =
> $this->getDbTable()->fetchAll($this->getDbTable()->select()->where('us
> er_id
> = ?', $userId));
> 
>         $entries   = array();
>         foreach ($resultSet as $row) {
>             $entry = new Model_List();
>             $entry->setId($row->id)
>                   ->setEmail($row->email)
>                   ->setComment($row->comment)
>                   ->setCreated($row->created)
>                   ->setMapper($this);
> 
>             $entries[] = $entry;
>         }
>         return $entries;
>     }
> 
> or is there better way.
> 
> 
> --
> View this message in context: 
> http://www.nabble.com/Zend-Model-and-quickstart-tp23445168p23445168.ht
> ml Sent from the Zend Framework mailing list archive at Nabble.com.
> 

--
Matthew Weier O'Phinney
Project Lead            | [email protected]
Zend Framework          | http://framework.zend.com/

Reply via email to