I'm relatively new to Object Oriented Programming. I pretty much understand the concepts, but practically speaking, I am having a really hard time finding information about how to best use Models in my Zend Framework applications.
Specifically, I have a Model (that doesn't extend anything) that doesn't use a Database Table. It uses getters and setters to access its protected members. I find myself struggling with how to best display this model in the view. I don't want logic in my view templates, but I find myself in the following situation:
In my controller:
$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object;
In my view template:
<h2><?= $this->object->getName() ?></h2>
I don't really like calling functions in my view templates but I don't know a better way to do this. I don't want my Model's members to be public, but I basically want to achieve the same results:
<h2><?= $this->object->name ?></h2>
I don't want my controller to do all the work of having to know everything about the model:
$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object;
$this->view->object->name = $object->getName();
What is the best practice of using models in the Zend Framework? Can anyone recommend any tutorial that would help me understand this Model/View dilemma in Zend Framework?
One possibility is to use the magic __set and __get methods in PHP. I use them like so within my abstract Model class:
abstract class Model_Abstract
{
protected $_data;
// Private Data Members assigned to protected $_data
public function __construct($data = null)
{
// Makes it so that I can pass in an associative array as well as
// an StdObject.
if(!is_object($data)) {
$data = (object) $data;
}
$this->_data = $data;
}
public function __get($key)
{
if (method_exists($this, '_get' . ucfirst($key))) {
$method = '_get' . ucfirst($key);
return $this->$method();
}
else {
return $this->_data->$key;
}
}
public function __set($key, $val)
{
if ( method_exists( $this, '_set' . ucfirst($key) ) ) {
$method = '_set' . ucfirst($key);
return $this->$method($val);
}
else {
$this->_data->$key = $val;
return $this->_data->$key;
}
}
}
class Model_User extends Model_Abstract
{
//Example overriding method for the property firstName in the $_data collection.
protected function _getFirstName()
{
// Do some special processing and then output the first name.
}
}
This makes it so that you can specify getters and setters for properties as necessary but makes it so that you don't have to define boilerplate functions for every property, just the ones where you want to do some sort of processing on it before returning the value. For example I use the functionality in a number of places to change ISO compliant dates (as stored in MySQL) into a more compact and readable format for users.
As far as what to place in your controller, I would recommend looking at this post for some specific feedback on what handling to place within your controller.
Some feel that they would rather have a helper that automatically loads models into the view and skirts the controller altogether. Personally I would say that within the context of Zend Framework and PHP it makes plenty of sense to pass models into the view from the controller because the state of the models in the view frequently depends on what came from the request (which should definitely be handled in the controller).
Update: As per criticisms in the comments, one thing that I would point out is that your database access layer and domain (or model) layer are really two different things, though with the Active Record they are blended together. I asked this question a while back and received some useful feedback on this matter. Whatever you decide to do with the model, you'll want to provide a consistent API for all domain objects regardless of where the data for the model comes from.
I suppose that one benefit offered by Saem's answer is that it offers the ability to directly map properties / function return values from one or more domain objects to the view object. Theoretically the usage within the view then looks like this:
// Mapped from Model_User::_data->last_name and Model_User::_data->first_name
$this->name
If only other developers are going to be working with the templates, I would recommend just passing in the models. Here is a link to a Jeff Atwood post on MVC Understanding Model-View-Controller
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With