Zend Framework:モデルとビューの使用、ベストプラクティス[非公開]
-
03-07-2019 - |
質問
私はオブジェクト指向プログラミングに比較的慣れていません。私は概念をほとんど理解していますが、実際には、Zend Frameworkアプリケーションでモデルを最適に使用する方法についての情報を見つけるのに本当に苦労しています。
具体的には、データベーステーブルを使用しないモデル(何も拡張しない)があります。ゲッターとセッターを使用して、保護されたメンバーにアクセスします。ビューにこのモデルを最適に表示する方法に苦労しています。ビューテンプレートにロジックは必要ありませんが、次のような状況に陥ります。
コントローラー内:
$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でこのModel / Viewのジレンマを理解するのに役立つチュートリアルを誰かお勧めできますか?
解決
可能性の1つは、PHPでマジックの__setおよび__getメソッドを使用することです。私は抽象Modelクラス内で次のように使用します:
abstract class Model_Abstract
{
protected 可能性の1つは、PHPでマジックの__setおよび__getメソッドを使用することです。私は抽象Modelクラス内で次のように使用します:
// Mapped from Model_User::_data->last_name and Model_User::_data->first_name
$this->name
これにより、必要に応じてプロパティのゲッターとセッターを指定できるようになりますが、すべてのプロパティに対してボイラープレート関数を定義する必要がなく、その上で何らかの処理を行う必要があるだけです値を返す前。たとえば、多くの場所でこの機能を使用して、ISO準拠の日付(MySQLに保存されている日付)をユーザーにとってよりコンパクトで読みやすい形式に変更します。
コントローラに何を配置するかについては、この投稿では、コントローラー内でどのような処理を行うべきかについての具体的なフィードバックが得られます。
ビューにモデルを自動的にロードし、コントローラーを完全に回避するヘルパーが必要だと感じる人もいます。個人的に私は、Zend FrameworkとPHPのコンテキスト内では、ビュー内のモデルの状態はリクエストから来たものに依存することが多いため、コントローラーからビューにモデルを渡すことは非常に理にかなっていると思いますコントローラーで)。
更新:コメントの批判によると、私が指摘したいことの1つは、データベースアクセスレイヤーとドメイン(またはモデル)レイヤーは、実際には2つの異なるものであるということです。それらは一緒にブレンドされます。 この質問をしばらく前に聞いて、いくつかの有用なフィードバックを受けましたこの問題について。モデルで何をするにしても、モデルのデータがどこから来たかに関係なく、すべてのドメインオブジェクトに一貫したAPIを提供する必要があります。
Saemの答えが提供する利点の1つは、1つまたは複数のドメインオブジェクトからビューオブジェクトにプロパティ/関数の戻り値を直接マッピングできることです。理論的には、ビュー内の使用法は次のようになります。
<*>data;
// Private Data Members assigned to protected 可能性の1つは、PHPでマジックの__setおよび__getメソッドを使用することです。私は抽象Modelクラス内で次のように使用します:
<*>
これにより、必要に応じてプロパティのゲッターとセッターを指定できるようになりますが、すべてのプロパティに対してボイラープレート関数を定義する必要がなく、その上で何らかの処理を行う必要があるだけです値を返す前。たとえば、多くの場所でこの機能を使用して、ISO準拠の日付(MySQLに保存されている日付)をユーザーにとってよりコンパクトで読みやすい形式に変更します。
コントローラに何を配置するかについては、この投稿では、コントローラー内でどのような処理を行うべきかについての具体的なフィードバックが得られます。
ビューにモデルを自動的にロードし、コントローラーを完全に回避するヘルパーが必要だと感じる人もいます。個人的に私は、Zend FrameworkとPHPのコンテキスト内では、ビュー内のモデルの状態はリクエストから来たものに依存することが多いため、コントローラーからビューにモデルを渡すことは非常に理にかなっていると思いますコントローラーで)。
更新:コメントの批判によると、私が指摘したいことの1つは、データベースアクセスレイヤーとドメイン(またはモデル)レイヤーは、実際には2つの異なるものであるということです。それらは一緒にブレンドされます。 この質問をしばらく前に聞いて、いくつかの有用なフィードバックを受けましたこの問題について。モデルで何をするにしても、モデルのデータがどこから来たかに関係なく、すべてのドメインオブジェクトに一貫したAPIを提供する必要があります。
Saemの答えが提供する利点の1つは、1つまたは複数のドメインオブジェクトからビューオブジェクトにプロパティ/関数の戻り値を直接マッピングできることです。理論的には、ビュー内の使用法は次のようになります。
<*>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 可能性の1つは、PHPでマジックの__setおよび__getメソッドを使用することです。私は抽象Modelクラス内で次のように使用します:
<*>
これにより、必要に応じてプロパティのゲッターとセッターを指定できるようになりますが、すべてのプロパティに対してボイラープレート関数を定義する必要がなく、その上で何らかの処理を行う必要があるだけです値を返す前。たとえば、多くの場所でこの機能を使用して、ISO準拠の日付(MySQLに保存されている日付)をユーザーにとってよりコンパクトで読みやすい形式に変更します。
コントローラに何を配置するかについては、この投稿では、コントローラー内でどのような処理を行うべきかについての具体的なフィードバックが得られます。
ビューにモデルを自動的にロードし、コントローラーを完全に回避するヘルパーが必要だと感じる人もいます。個人的に私は、Zend FrameworkとPHPのコンテキスト内では、ビュー内のモデルの状態はリクエストから来たものに依存することが多いため、コントローラーからビューにモデルを渡すことは非常に理にかなっていると思いますコントローラーで)。
更新:コメントの批判によると、私が指摘したいことの1つは、データベースアクセスレイヤーとドメイン(またはモデル)レイヤーは、実際には2つの異なるものであるということです。それらは一緒にブレンドされます。 この質問をしばらく前に聞いて、いくつかの有用なフィードバックを受けましたこの問題について。モデルで何をするにしても、モデルのデータがどこから来たかに関係なく、すべてのドメインオブジェクトに一貫したAPIを提供する必要があります。
Saemの答えが提供する利点の1つは、1つまたは複数のドメインオブジェクトからビューオブジェクトにプロパティ/関数の戻り値を直接マッピングできることです。理論的には、ビュー内の使用法は次のようになります。
<*>data collection.
protected function _getFirstName()
{
// Do some special processing and then output the first name.
}
}
これにより、必要に応じてプロパティのゲッターとセッターを指定できるようになりますが、すべてのプロパティに対してボイラープレート関数を定義する必要がなく、その上で何らかの処理を行う必要があるだけです値を返す前。たとえば、多くの場所でこの機能を使用して、ISO準拠の日付(MySQLに保存されている日付)をユーザーにとってよりコンパクトで読みやすい形式に変更します。
コントローラに何を配置するかについては、この投稿では、コントローラー内でどのような処理を行うべきかについての具体的なフィードバックが得られます。
ビューにモデルを自動的にロードし、コントローラーを完全に回避するヘルパーが必要だと感じる人もいます。個人的に私は、Zend FrameworkとPHPのコンテキスト内では、ビュー内のモデルの状態はリクエストから来たものに依存することが多いため、コントローラーからビューにモデルを渡すことは非常に理にかなっていると思いますコントローラーで)。
更新:コメントの批判によると、私が指摘したいことの1つは、データベースアクセスレイヤーとドメイン(またはモデル)レイヤーは、実際には2つの異なるものであるということです。それらは一緒にブレンドされます。 この質問をしばらく前に聞いて、いくつかの有用なフィードバックを受けましたこの問題について。モデルで何をするにしても、モデルのデータがどこから来たかに関係なく、すべてのドメインオブジェクトに一貫したAPIを提供する必要があります。
Saemの答えが提供する利点の1つは、1つまたは複数のドメインオブジェクトからビューオブジェクトにプロパティ/関数の戻り値を直接マッピングできることです。理論的には、ビュー内の使用法は次のようになります。
<*>他のヒント
他の開発者のみがテンプレートを使用する場合は、モデルを渡すことをお勧めします。 MVC Model-View-Controllerについて
これは特にzendフレームワーク向けではありませんが、私の考えでは問題はかなり一般的です。
コントローラ内でモデルをビューに配線するのではなく、正しい道を進んでいるようです。むしろ、その抽象的で、大量のモデルをマッピングする場合、または同じモデルを何度もマッピングする場合に特に重要です。
簡単なことは、一連のマッピング関数を記述することです。これは、同じものを繰り返しマッピングすることを避けていれば問題ありません。
より一般的なソリューションが必要な場合は、そのボイラープレートコードの記述を避け、物事をよりドライに保つことにも対処し、マッパークラスを作成することをお勧めします。
ViewModelMapperを作成して、1つまたは複数のモデルを取得し、それらをビューにマップできます。
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
}
}
これをコントローラーにインスタンス化し、マッピングをセットアップすると、コントローラーがマッピングを制御しますが、まれな例外を除き、すべてのコントローラーマップについて、すべてのボイラープレートとコーディングロジックが集中化されます。
モデルアーキテクチャの詳細については、この投稿を読む。ビューについては特に言及していませんが、読む価値は間違いありません。
最終的に getViewClass()
関数をモデルに追加しました。コントローラーはこの関数を呼び出して、他の方法ではアクセスできない保護された変数を取得します。また、ビューはゲッターの呼び出しを心配する必要はありません。
//controller
$object = new Object();
$object->setName('Foo Bar');
$this->view->object = $object->getViewClass();
//view template
<h2><?= $this->object->name ?></h2>
Zend Frameworkでジョブを完了するためのより良い方法があるかどうかはわかりませんが、これは1つのソリューションです。