2009-03-02 16 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 Frameworkのこのモデル/ビューのジレンマを理解するのに役立つチュートリアルをお勧めしますか?

答えて

4

1つの可能性は、PHPで魔法の__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. 
    } 
} 

これは、必要に応じてプロパティのゲッターとセッターを指定できるようにしますが、あなたはすべてのプロパティのための定型関数を定義する必要がないようにそれを作ります、値を返す前に何らかの処理をしたいところだけです。たとえば、ISO準拠の日付を(MySQLに格納されているように)よりコンパクトで読みやすい形式に変更するために、さまざまな場所で機能を使用します。

コントローラーに配置する範囲では、コントローラー内のどのような取り扱いについての具体的なフィードバックについては、this postを参照することをお勧めします。

モデルに自動的にモデルを読み込んでコントローラ全体をスカラーにするヘルパーがいると感じる人もいます。個人的には、Zend FrameworkとPHPの文脈の中では、ビュー内のモデルの状態が要求から来たものに依存しているため、コントローラからのビューにモデルを渡すのは十分に意味があると言います。コントローラ内の)。

更新:コメント欄に批判あたりのように、私が指摘するだろう一つのことは、アクティブレコードと、彼らが一緒にブレンドされているものの、データベースアクセス層とドメイン(またはモデル)層は、実際には2つの異なるものであるということです。私はthis questionにしばらく前に尋ねて、この問題についていくつかの有用なフィードバックを受けました。モデルを使って何をすることにしても、モデルのデータがどこに由来するかにかかわらず、すべてのドメインオブジェクトに対して一貫したAPIを提供したいと思うでしょう。

私はSaemの答えによって提供される1つの利点は、1つ以上のドメインオブジェクトからビューオブジェクトにプロパティ/関数の戻り値を直接マップする機能を提供するということです。モデルアーキテクチャ上で良好な読み取りのために

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

これは実際にはやり方が悪い方法です。フォームとの間でシリアル化する必要があるかどうかに関係なく、すべてのプロパティに任意のアクセス権を与えるだけでなく、実際に求められているマッピングの概念でモデルをオーバーロードします。 – Saem

+0

フォームロジックをモデルに組み込むことで、ビューとモデルのミックスも悪くなります。すでに述べたように、デフォルトの動作をオーバーライドするのは非常に簡単で、愚かな定型的なgetterとsetterを作成する必要はありません。 –

+0

Zend_Db_Table_Rowクラスを見ると、Zendは実際には同様の原則を使用して、テーブルのフィールドとその値を公開しています。 –

3

他の開発者だけがテンプレートを使用している場合は、モデルを渡すことをおすすめします。以下は、MVCのJeff Atwoodの投稿へのリンクです。Understanding Model-View-Controller

3

これは特にzendフレームワーク向けではありませんが、問題はかなり一般的です。

モデルをハードウェアでコントローラに配線するのではなく、正しいパスにいるようです。あなたはその抽象的なものを持っているでしょう。特に、1トンのモデルをマッピングしたり、同じモデルを何度も繰り返しマッピングする場合は重要です。

シンプルなことは、たくさんのマッピング関数を書くことです。これは、避けようとしているのは同じことを何度も何度も繰り返しマッピングしていれば問題ありません。

さらに一般的な解決策を望むなら、ボイラープレートのコードを書くことを避け、物事をよりドライな状態に保つことを念頭に置いて、マッパークラスを作成することをお勧めします。

モデルを使用する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クラスを使用する関連する例を示してください。現時点では、Viewにモデルを追加する方法がより複雑になっています。 –

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で仕事をするより良い方法があるのか​​どうかはわかりませんが、これは一つの解決策です。

関連する問題