web-dev-qa-db-ja.com

Zend Frameworkのモデル

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

私は基本的な_class User extends Zend_Db_Table_Abstract_を見て、それをコントローラーに呼び出します:

_$foo = new User;_

$foo->fetchAll()

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


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

33
rg88

私はZend_Db_Table_AbstractZend_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の設計の意図に従うようにしています。 (これは私の 主題に関する考えとリンク の詳細です)。このアプローチは少しクラスが重くなりますが、入力の処理とビューとの調整にコントローラが集中しているように感じます。アプリケーション固有の作業を行うためにモデルを残します。

23
Barrett Conrad

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

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

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

これはIS-Aの例です。

class MyModel extends Zend_Db_Table_Abstract
{
} 

これはHAS-Aの例です。

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

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

また、マーティンファウラーの ドメインモデル 設計パターンに関する見解、および 貧血ドメインモデル アンチパターンに関する彼の説明を読むこともできます。これは、残念ながら多くの開発者がOOプログラミング。

61
Bill Karwin

Zend_Db_Tableをモデルとして使用しないでください。それはあなたを困らせるだけです。 Zend_Db_Tableを使用してデータベースと対話する独自のモデルクラスを作成するか、私のブログ投稿 here を読んで、「モデル」クラスとZend_Db_Tableをいくらか組み合わせることができるハックを探してください。

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

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

7
smack0007

私はModels for ZFについていくつかの調査を行っており、Matthew Weier O'Phinneyによる興味深い一連の記事を見つけました。

これは「量産コード」ではなく、想像力に委ねられていますが、読みやすく、かなり役に立ちました。

7
ironkeith

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

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

5
d-_-b

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

代わりに、モデルの Doctrine を見てください。 PHPのデファクトORMになりつつあります。

3
chroder

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

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

モデルはZend_Db_Table_Abstractを拡張して、データへのアクセスプロセスを簡単にしますが、そのデータで実現できる機能は、すべてあなたの創造性とニーズにかかっています。 Cal Evans著の本「php | architect's guide to programming with zend framework」をお勧めします。本は非常に有益で読みやすいです。第4章と第6章はこの問題に役立ちます。

1
farzad

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

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

1
sunwukung

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

「ユーザー」テーブルの例:

レベル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);
1
lo_fye

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

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

1
troelskn

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

$select = $table->select();
$select->from($table,
              array('COUNT(reported_by) as `count`', 'reported_by'))
       ->where('bug_status = ?', 'NEW')
       ->group('reported_by');
1
CMS