Proper setup of Controller/Model in Zend Framework
I have an action in my controller called createAction
. I also have a model My_Application_Product
, that I'm using to create the product within the system. I'm following the Architecting Your Models talk. Is this the "correct" way to save my product? Code for My_Application_Product
follows below.
class ProductController extends Zend_Controller_Action {
public function createAction() {
$categoryAdapter = new Application_Model_Categories();
$categories = $categoryAdapter->fetchAll('parent_id IS NOT NULL');
$form = new My_Application_Forms_Product_Create();
$category = $form->getElement('category');
foreach ($categories as $cat) {
$category->addMultiOption($cat->id, $cat->name);
}
if ($this->getRequest()->isPost()) {
if (! $form->isValid($_POST)) {
$this->view->form = $form;
return $this->render('create');
}
$product = new My_Application_Product();
$product->name = $_POST['name'];
$product->company_id = 1;
$product->category_id = $_POST['category'];
$product->trade_names = $_POST['trade_names'];
$product->website = $_POST['website'];
$product->description = $_POST['description'];
$product->closed_loop = $_POST['closed_loop'];
$product->sold_as = $_POST['sold_as'];
$product->sold_in = $_POST['sold_in'];
$product->dilution = $_POST['dilution'];
$id = $product->save();
$url = $this->getHelper('Url')
->url(array('action' => 'registryservices', 'id' => $id));
$this->_redirect($url);
}
$this->view->form = $form;
}
}
'
class My_Application_Product implements My_Application_Product_Inter开发者_JS百科face {
// declare all the internally used variables here.
// if something isn't showing up when trying to save, that's probably
// because it's missing from here
protected $_id;
protected $_name;
protected $_company_id;
protected $_trade_names;
protected $_website;
protected $_description;
protected $_closed_loop;
protected $_sold_as;
protected $_sold_in;
protected $_dilution;
protected $_category_id;
protected $_verification_level;
protected $_dfe_sccp;
protected $_dfe_siicp;
protected $_el_ccd_hsc;
public function __set($name, $value) {
$local_var_name = "_" . $name;
if (property_exists($this, $local_var_name)) {
$this->{$local_var_name} = $value;
}
}
public function __get($name) {
$local_var_name = "_" . $name;
if (property_exists($this, $local_var_name)) {
return $this->{$local_var_name};
}
}
/**
*
* @param array $data The data to save
*/
public function save() {
// this means we're editing something
if ($this->id) {
$table = new My_Application_Product_Table();
$data = $table->find($this->id)->toArray();
$data = $data[0];
foreach (get_class_vars(get_class($this)) as $key => $value) {
if (! is_null($this->$key)) {
$data[preg_replace('/^_/', '', $key)] = $this->$key;
}
}
$id = $table->update($data, sprintf('id = %d', $this->id));
// this means we're creating, and this is the data we need
} else {
$data = array(
'id' => rand(1,1000000),
'name' => $this->name,
'date_created' => date('Y-m-d H:i:s'),
);
$id = $table->insert($data);
}
return $id;
}
}
'
class My_Application_Product_Table extends Zend_Db_Table_Abstract {
protected $_name = 'products';
protected $_primary = 'id';
}
Split your model in multiple classes :
- 1 class representing the entity (no methods, except for accessors).
this class represents your "real-life" object, and is just a structured data container, which encapsulates data
class My_Application_Model_Product {
protected $_id;
protected $_name;
protected $_company_id;
protected $_trade_names;
protected $_website;
//...
public function __set($name, $value) {
//Implement your setter here
}
public function __get($name) {
}
}
- 1 class responsible of data mapping.
This class makes is the link between your data source (database, webservice, file...) and your entity.
Class My_Application_Model_DataMapper_Product {
protected $_adapter
public function __construct($adapter)
{
$this->setAdapter($adapter);
}
public function setAdapter($adapter)
{
$this->_adapter = $adapter;
}
public function save(My_Application_Model_Product $product)
{
//Perform your save operation here
}
public function fetchAll()
{
}
public function findById($id)
{
}
//You may implement specific methods for any needed specific operation (search, bulk-update...
}
- a third class for data access and persistence (Zend_Db_table, Soap client...) This third class is passed to the datamapper as the adapter and is used inside the methods to getch/save data.
With this architecture, you have a clear separation of responsibilities, and may change one part without affecting the other : for example, you could switch from a database to a webservice without affecting your Product class.
A very simple example is given in the zf Quickstart
精彩评论