Zend框架中控制器/模型的正确设置


Proper setup of Controller/Model in Zend Framework

我有一个动作在我的控制器称为createAction。我还有一个模型My_Application_Product,我用它来生成系统内的产物。我正在听"构建你的模型"的演讲。这是保存我的产品的"正确"方法吗?My_Application_Product代码如下:

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_Interface {
    // 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';
}

将模型拆分为多个类:

  • 一个表示实体的类(没有方法,除了访问器)。

这个类代表你的"真实的"对象,它只是一个结构化的数据容器,封装了数据

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类负责数据映射。

这个类是你的数据源(数据库,webservice,文件…)和你的实体之间的链接。

 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...
 }
  • 第三类,用于数据访问和持久化(Zend_Db_table, Soap client…)第三个类作为适配器传递给数据映射器,并在方法中用于获取/保存数据。

有了这个体系结构,你就有了一个清晰的职责分离,并且可以在不影响其他部分的情况下改变一部分:例如,你可以从数据库切换到web服务而不影响你的Product类。

在zf快速入门

中给出了一个非常简单的例子