2009-03-02 48 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中完成工作,但這是一個解決方案。

相關問題