2009-03-02 44 views
9

我是面向对象编程的新手。我非常理解这些概念,但实际上,我很难在Zend Framework应用程序中找到有关如何最好地使用模型的信息。Zend Framework:使用模型和视图,最佳实践

具体来说,我有一个模型(不扩展任何东西),不使用数据库表。它使用getter和setter来访问其受保护的成员。我发现自己在如何在视图中最好地展示这个模型方面苦苦挣扎。我不想逻辑在我看来模板,但我发现自己在以下情况:

在我的控制器:

$object = new Object(); 
$object->setName('Foo Bar'); 
$this->view->object = $object; 

在我的视图模板:

<h2><?= $this->object->getName() ?></h2> 

我不我真的很喜欢在我的视图模板中调用函数,但我不知道更好的方法来做到这一点。我不希望我的模型的成员是公开的,但我基本上要达到同样的结果:

<h2><?= $this->object->name ?></h2> 

我不希望我的控制器做不必了解模型的一切的一切工作:

$object = new Object(); 
$object->setName('Foo Bar'); 
$this->view->object = $object; 
$this->view->object->name = $object->getName(); 

在Zend Framework中使用模型的最佳实践是什么?任何人都可以推荐任何教程,以帮助我理解Zend框架中的这种模型/视图困境?

回答

4

一种可能性是在PHP中使用magic __set和__get方法。我使用它们像这样我的抽象模型类中:

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. 
    } 
} 

这使得它,以便您可以指定为必要的属性getter和setter,但使得它,这样你就不必定义每个属性样板功能,只是你想在返回值之前对它进行某种处理的那些。例如,我使用许多地方的功能来将ISO兼容日期(如存储在MySQL中)更改为用户更紧凑和可读的格式。

至于要在控制器中放置什么,我建议您在this post上查看关于在控制器内部放置什么样的特定反馈。

有些人觉得他们宁愿有一个帮手,可以自动将模型加载到视图中,并完全控制控制器。就我个人而言,我认为在Zend Framework和PHP的上下文中,将模型传递到控制器的视图是非常有意义的,因为视图中模型的状态经常取决于请求的内容(应该明确处理在控制器中)。

更新:根据评论中的批评,我要指出的一件事情是,您的数据库访问层和域(或模型)层实际上是两个不同的东西,尽管使用Active Record它们混合在一起。我问了this question,并在这个问题上收到了一些有用的反馈。无论您决定如何处理模型,无论模型的数据来自何处,您都希望为所有域对象提供一致的API。

我想Saem的答案提供的一个好处是它提供了直接将属性/函数返回值从一个或多个域对象映射到视图对象的功能。理论上,在视图中使用则是这样的:

// Mapped from Model_User::_data->last_name and Model_User::_data->first_name 
$this->name 
+1

这实际上是一种糟糕的做事方式。您不仅可以任意访问所有属性,无论它们是否应该(从)表单到/从表单的序列化,还会使用映射的概念重载模型,这是实际要求的。 – Saem 2009-03-03 00:47:40

3

这不是特别针对zend框架,但问题是相当普遍的,在我看来。

看来你是在正确的道路上,而不是将模型硬连线到控制器内部的视图。如果您要绘制大量模型或反复绘制同一模型,则您更愿意拥有该抽象,尤其重要。

一件简单的事情就是编写一堆映射函数,如果你正在避免的是反复映射相同的东西,那很好。

如果你想要一个更通用的解决方案,这也解决了避免写入锅炉板代码,并让事情更干,我建议创建一个映射类。

您可以创建一个ViewModelMapper,它需要一个模型或几个模型并将它们映射到视图。

class ViewModelMapper 
{ 
    public function __construct($view) 
    { 
     //set the properties 
    } 

    public function addModel($model, $overrideViewProperty = null) 
    { 
     //add the model to the list of models to map, use the view's property 
     // name to figure out what to map it to? Allow for an override just in case. 
    } 

    public function getMappedView() 
    { 
     //take the view, map all the models 
    } 
} 

,你可以再比如这个控制器上,并设置映射,所以控制器控制的映射还在,但所有的锅炉板和编码逻辑集中,所有控制器的地图,除了极少数例外。

+0

请提供一个使用此Mapper类的相关示例。截至目前,我所看到的只是一种让视图更加复杂的模型添加方法。 – 2009-03-03 01:48:55

1

有关模型架构,read this post很好看。它没有具体谈论这个观点,但绝对值得一读。

我最终为我的模型添加了getViewClass()函数。控制器调用这个函数来获得它不会访问的受保护的变量,并且视图不必担心调用任何获取器。

//controller 
$object = new Object(); 
$object->setName('Foo Bar'); 
$this->view->object = $object->getViewClass(); 

//view template 
<h2><?= $this->object->name ?></h2> 

我不知道是否有更好的方式在Zend Framework中完成工作,但这是一个解决方案。

相关问题