33

Zend Framework でモデルを実装した方法にはどのようなものがありますか?

私は基本的なものを見てclass User extends Zend_Db_Table_Abstract、それをコントローラーに呼び出しました:

$foo = new User;

$foo->fetchAll()

しかし、より洗練された使い方はどうでしょうか? ドキュメントのクイックスタート セクションではそのような例を提供していますが、Zend Framework のモデルの「最適な使用法」の例が得られていないように感じます。興味深い実装はありますか?


編集:(CMSのコメントに応じて)明確にする必要があります...より複雑な選択を行うことについて知っています。私は、モデルの概念に対する全体的なアプローチと、他の人がそれらをどのように実装したかの具体的な例に興味がありました (基本的に、マニュアルで省略されているものと、基本的なハウツーで見過ごされているもの)。

4

11 に答える 11

61

私は Zend で働いており、Zend_Db_Table コンポーネントでかなりの作業を行いました。

Zend Framework は、ドメイン モデル パターンに関して「モデル」の概念について多くのガイダンスを提供していません。モデルはアプリケーションに固有のビジネス ロジックの一部をカプセル化するため、モデルの基本クラスはありません。このテーマについて詳しくブログを書きました。

データベースへの永続性は、モデルの内部実装の詳細である必要があります。モデルは通常、 1 つ以上のテーブルを使用します。モデルをテーブルの拡張と見なすのは、一般的ですが不適切なオブジェクト指向設計です。つまり、Model IS-A Table ではなく、Model HAS-A Table と言うべきです。

これは IS-A の例です。

class MyModel extends Zend_Db_Table_Abstract
{
} 

これは HAS-A の例です。

class MyModel // extends nothing
{
    protected $some_table;
}

実際のドメイン モデルでは、MyModel のメソッドで $some_table を使用します。

ドメイン モデルデザイン パターンに関する Martin Fowler の見解と、 Anemic Domain Modelアンチパターンに関する彼の説明も読むことができます。

于 2008-11-17T07:23:03.157 に答える
23

Zend_Db_Table_Abstract私は個人的にとの両方をサブクラス化しZend_Db_Table_Row_Abstractます。私のコードとあなたのコードの主な違いは、のサブクラスをZend_Db_Table_Abstract「テーブル」およびZend_Db_Table_Row_Abstract「行」として明示的に扱うことです。コントローラーにオブジェクト、SQL、または組み込みのZFデータベースメソッドを直接呼び出すことはめったにありません。私は次のように、特定のレコードを要求して背後で呼び出すロジックを非表示にしようとしていますZend_Db_Table_Abstract

class Users extends Zend_Db_Table_Abstract {

    protected $_name = 'users';

    protected $_rowClass = 'User'; // <== THIS IS REALLY HELPFUL

    public function getById($id) {
        // RETURNS ONE INSTANCE OF 'User'
    }

    public function getActiveUsers() {
        // RETURNS MULTIPLE 'User' OBJECTS            
    }

}

class User extends Zend_Db_Table_Row_Abstract {

    public function setPassword() {
        // SET THE PASSWORD FOR A SINGLE ROW
    }

}

/* CONTROLLER */
public function setPasswordAction() {

    /* GET YOUR PARAMS */

    $users = new Users();

    $user = $users->getById($id);

    $user->setPassword($password);

    $user->save();
}

これにアプローチする方法はたくさんあります。これだけではないと思いますが、私はZFの設計の意図に従おうとしています。(このテーマに関する私の考えとリンクの詳細は次のとおりです。)このアプローチは少しクラスが重くなりますが、コントローラーが入力の処理とビューとの調整に集中し続けるように感じます。アプリケーション固有の作業を行うためにモデルを離れます。

于 2008-11-17T05:22:02.620 に答える
7

私は ZF のモデルについていくつかの調査を行っており、Matthew Weier O'Phinney による興味深い一連の記事に出くわしました。これらはチェックする価値があります。

これは「製品コード」ではなく、多くは想像に委ねられていますが、よく読んでかなり役に立ちました。

于 2009-01-26T21:40:16.440 に答える
7

Zend_Db_Table をモデルとして使用しないでください。それはあなたを困らせるだけです。Zend_Db_Table を使用してデータベースと対話する独自のモデル クラスを作成するか、"Model" クラスと Zend_Db_Table をある程度組み合わせることができるハックについて、こちらのブログ投稿を参照してください。

主に避けるべきことは、Zend_Db_Table をコントローラーで直接使用すると、複数の場所で同じことを行うことになるということです。そのロジックの一部を変更する必要がある場合は、複数の場所を変更する必要があります。良くない。私の最初のプロのプロジェクトはこのように行われました。会社で ZF の使用方法を学ばなければならなかったのは私だったのですが、今では完全に混乱しています。

また、洗練されたフェッチのためにヘルパー関数をクラスに記述する傾向があります。$table->doNameFetchAll() や $table->doOrderFetchAll() のようなもの。

于 2008-11-17T08:43:22.887 に答える
5

モデルはデータベースとは何の関係もありません。RSS フィードや SOAP サービスからデータをフェッチしたり、FS からファイルを読み取ったりするとどうなりますか?

こういったものをすべてモデルに入れています。その場合、私のモデル クラスは何も拡張しない可能性があります。他のモデルのメソッドを使用するモデルを書こうとしています。

于 2010-10-29T11:41:16.667 に答える
3

モデル部分のZFをスキップすると、はるかに優れたソリューションがあります。ZFの「MVC」の「M」はほとんどありません。彼らのドキュメントを読んで、彼らは実際にはモデルについてまったく言及していません-これは良いことです、それはあなたがたくさんのアダプターコードを書かなくてもあなたが望むほとんど何でも使うことができることを意味します。

代わりに、モデルのDoctrineを見てください。それはすぐにPHPの事実上のORMになりつつあります。

于 2008-11-17T05:07:14.943 に答える
1

Zend_Db_Tableの代わりにPropel1.3を使用しています。セットアップは難しいですが、素晴らしいです。データベースを調べて、すべてのモデルを自動生成できます。実際には2つのレベルと2つのタイプのモデルが生成されます。

'user'テーブルの例:

レベル1:BaseModelとBasePeer:ORMを再生成するたびに、これらは上書きされます。すなわちBaseUser.php&BaseUserPeer.php

レベル2:StubModelとStubPeer:これらは上書きされません。それらはあなたがカスタマイズするものです。すなわちUser.php&UserPeer.php

タイプ1:モデル-基本的なCRUD操作用であり、クエリではありません。つまり、User.phpタイプ2:ピア-クエリ用です。これらは静的オブジェクトです。すなわちUserPeer.php

したがって、ユーザーを作成するには:

$derek = new User();
$derek->setFirstName('Derek');
$derek->save();

すべてのderekを見つけるには:

$c = new Criteria();
$c->add(UserPeer::FIRST_NAME, 'Derek');
$dereks = UserPeer::doSelect($c);
于 2009-01-30T14:52:16.023 に答える
1

より複雑なクエリを実行できます。マニュアルページの「高度な使用法」セクションを確認してください。Zend_Db_Table

$select = $table->select();
$select->from($table,
              array('COUNT(reported_by) as `count`', 'reported_by'))
       ->where('bug_status = ?', 'NEW')
       ->group('reported_by');
于 2008-11-17T04:39:22.317 に答える
1

Zend_Db_Table_Abstractクラスを拡張し、それにいくつかの便利なメソッドを追加できます。たとえば、changePassword()メソッドをユーザークラスに追加して、そのデータを操作できます。または、クラスのデフォルトの__toString()メソッドを変更して、カスタマイズされた__toString()メソッドを作成します。たとえば、ユーザーの連絡先情報全体(名前、住所、電話番号)を適切な形式の文字列で返します。 。コンストラクターでは、データをオブジェクトのプロパティに入力できます。次に、次のように使用します。

public function __toString() {
   $data = $this->_name . ', ' . $this->_adderss . ', call: ' . $this->_phone;
   return $data;
}

モデルは、データへのアクセスプロセスを容易にするためにZend_Db_Table_Abstractを拡張しますが、そのデータで使用できる機能はすべて、創造性とニーズに依存します。CalEvansによる「php|architectのzendフレームワークを使用したプログラミングガイド」という本をお勧めします。この本は非常に有益で読みやすいです。第4章と第6章は、この問題に役立つでしょう。

于 2008-11-17T05:00:45.847 に答える
1

http://zfsite.andreinikolov.com/2008/08/zend_db_table-time-overhead-about-25-percents/

ちょっとした落とし穴22、Zend_Tableは原則としては優れていますが、パフォーマンスのオーバーヘッドが発生します(キャッシュなし)...

于 2010-04-06T14:58:55.967 に答える
1

データベース エンティティは、唯一の種類のモデル コンポーネントではありません。そのため、モデル (複数形) について話すことはあまり意味がありません。アプリケーションには、多数のコンポーネントを含む1 つのモデルがあります。これらのコンポーネントの一部はテーブル ゲートウェイになる可能性があり (したがって から拡張されますZend_Db)、そうでないものもあります。

Eric Evans 著のDomain Driven Designという本を手に入れることをお勧めします。この本は、オブジェクト モデルの構築方法を見事に説明しています。

于 2008-11-17T20:55:55.403 に答える