Understanding models (zend framework) [long]
Posted: Fri Jun 26, 2009 5:53 am
Hey all. I'm not new to PHP, but I am very new to frameworks and any non homemade MVC setups. Of course, my home made ones are shoddy things at best, hence the decision to learn a tried and tested package.
Anyhow .... I'm wondering if anyone can help me out with understanding models.
I've gone through a few tutorials and I've seen two basic approaches to models. This may apply mainly to zend framework here, so bear with me.
The first method is what I more or less expected to find (code clipped from Akra’s DevNotes).
I look at that and I think "Ahhh ... so THATS how it's supposed to work". I still have questions about how this works ... but more on that later.
Anyhow ... I then rock on up to the official zend quickstart, and I see the model like this ...
After a fair amount of head scratching ... I think I get how this works.
application/models/Guestbook.php is pretty much an object version of the table, independent of the table itself.
application/models/GuestbookMapper.php is along the lines of the previous model style, but basically acts as an interface to convert the object to ...
application/models/DbTable/Guestbook.php - the straight Zend_Db_Table_Abstract object.
Some fumbling around has turned up that this is Object Relational Mapping.
My questions on this are basically ....
1. Why do it the second way? What benefits does it provide?
2. What about working with multiple tables .... such as displaying a SELECT with a JOIN. I've been told to create a model just pulling the SELECT data and then use have the controller open multiple models (i.e. the view for display, and whatever tables need changing for actions). I'm assuming that with either method I use I still have to open multiple models this way. This kind of leads me back to question one.
3. Well ... many more ... but let's stop here for the moment.
Any help anyone could give here would be great.
Cheers
Anyhow .... I'm wondering if anyone can help me out with understanding models.
I've gone through a few tutorials and I've seen two basic approaches to models. This may apply mainly to zend framework here, so bear with me.
The first method is what I more or less expected to find (code clipped from Akra’s DevNotes).
Code: Select all
<?php
// application/models/DbTable/Albums.php
class Model_DbTable_Albums extends Zend_Db_Table
{
protected $_name = 'albums';
public function getAlbum($id)
{
$id = (int)$id;
$row = $this->fetchRow('id = ' . $id);
if (!$row) {
throw new Exception("Count not find row $id");
}
return $row->toArray();
}
public function addAlbum($artist, $title)
{
$data = array(
'artist' => $artist,
'title' => $title,
);
$this->insert($data);
}
function updateAlbum($id, $artist, $title)
{
$data = array(
'artist' => $artist,
'title' => $title,
);
$this->update($data, 'id = '. (int)$id);
}
function deleteAlbum($id)
{
$this->delete('id =' . (int)$id);
}
}Anyhow ... I then rock on up to the official zend quickstart, and I see the model like this ...
Code: Select all
<?php
// application/models/DbTable/Guestbook.php
/**
* This is the DbTable class for the guestbook table.
*/
class Default_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
/** Table name */
protected $_name = 'guestbook';
}Code: Select all
<?php
// application/models/GuestbookMapper.php
class Default_Model_GuestbookMapper
{
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Default_Model_DbTable_Guestbook');
}
return $this->_dbTable;
}
public function save(Default_Model_Guestbook $guestbook)
{
$data = array(
'email' => $guestbook->getEmail(),
'comment' => $guestbook->getComment(),
'created' => date('Y-m-d H:i:s'),
);
if (null === ($id = $guestbook->getId())) {
unset($data['id']);
$this->getDbTable()->insert($data);
} else {
$this->getDbTable()->update($data, array('id = ?' => $id));
}
}
public function find($id, Default_Model_Guestbook $guestbook)
{
$result = $this->getDbTable()->find($id);
if (0 == count($result)) {
return;
}
$row = $result->current();
$guestbook->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created);
}
public function fetchAll()
{
$resultSet = $this->getDbTable()->fetchAll();
$entries = array();
foreach ($resultSet as $row) {
$entry = new Default_Model_Guestbook();
$entry->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created)
->setMapper($this);
$entries[] = $entry;
}
return $entries;
}
}Code: Select all
<?php
// application/models/Guestbook.php
class Default_Model_Guestbook
{
protected $_comment;
protected $_created;
protected $_email;
protected $_id;
protected $_mapper;
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
}
}
public function __set($name, $value)
{
$method = 'set' . $name;
if (('mapper' == $name) || !method_exists($this, $method)) {
throw new Exception('Invalid guestbook property');
}
$this->$method($value);
}
public function __get($name)
{
$method = 'get' . $name;
if (('mapper' == $name) || !method_exists($this, $method)) {
throw new Exception('Invalid guestbook property');
}
return $this->$method();
}
public function setOptions(array $options)
{
$methods = get_class_methods($this);
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
public function setComment($text)
{
$this->_comment = (string) $text;
return $this;
}
public function getComment()
{
return $this->_comment;
}
public function setEmail($email)
{
$this->_email = (string) $email;
return $this;
}
public function getEmail()
{
return $this->_email;
}
public function setCreated($ts)
{
$this->_created = $ts;
return $this;
}
public function getCreated()
{
return $this->_created;
}
public function setId($id)
{
$this->_id = (int) $id;
return $this;
}
public function getId()
{
return $this->_id;
}
public function setMapper($mapper)
{
$this->_mapper = $mapper;
return $this;
}
public function getMapper()
{
if (null === $this->_mapper) {
$this->setMapper(new Default_Model_GuestbookMapper());
}
return $this->_mapper;
}
public function save()
{
$this->getMapper()->save($this);
}
public function find($id)
{
$this->getMapper()->find($id, $this);
return $this;
}
public function fetchAll()
{
return $this->getMapper()->fetchAll();
}
}application/models/Guestbook.php is pretty much an object version of the table, independent of the table itself.
application/models/GuestbookMapper.php is along the lines of the previous model style, but basically acts as an interface to convert the object to ...
application/models/DbTable/Guestbook.php - the straight Zend_Db_Table_Abstract object.
Some fumbling around has turned up that this is Object Relational Mapping.
My questions on this are basically ....
1. Why do it the second way? What benefits does it provide?
2. What about working with multiple tables .... such as displaying a SELECT with a JOIN. I've been told to create a model just pulling the SELECT data and then use have the controller open multiple models (i.e. the view for display, and whatever tables need changing for actions). I'm assuming that with either method I use I still have to open multiple models this way. This kind of leads me back to question one.
3. Well ... many more ... but let's stop here for the moment.
Any help anyone could give here would be great.
Cheers