Zend Frameworkの名前付きスコープ

データベースを使用して、多くの検索方法を常に作成する必要があります。 典型的なシナリオは次のとおりです。



サイトのユーザーをリストする必要があるとします。 最初は、次のようになります-$ user_table-> fetchAll()。 そして、あなただけの女の子を表示したい場合はどうなりますか? getFemaleUsers()メソッドを書きましょう。 しかし、禁止されておらず、アバターを持っている人だけですか? そして、管理者パネルの結論は女の子だけのためですが、ユーザーのステータスを考慮しませんか?



最終的に、互いに部分的に重複する、または同じことを行うメソッドのワゴンを取得しますが、ソートのみが異なります。 しかし、彼らはまだテストする必要があります...







このアプローチには何の問題もありませんが、すぐに疲れます。 プロジェクトに複数の開発者がいる場合、同じことをするメソッドの名前が異なる場合があります。



このタスクには解決策があり、 名前付きスコープと呼ばれます 。 これはレールに実装され、次のようになります。



クラスUser <ActiveRecord :: Base
   named_scope:active ,: conditions => {:active => true}
   named_scope:inactive ,: conditions => {:active => false}
   named_scope:男性、:条件=> {:セックス=>男性}
終わり




 User.active#すべてのアクティブなユーザーを選択します
 User.inactive#すべての非アクティブなユーザーを選択します
 User.active.male#すべてのアクティブな男性を選択




少し説明。 rubyのメソッドは非常に頻繁に生成され、それらが呼び出されると、ブラケットはほとんど常に省略されます。 上記は、プロパティではなくメソッドの呼び出しです。



Zend Frameworkで同じものを実装する方法は? Zend_Db_Table_Selectが助けになります。 残念ながら、ZFでは通常の方法を使用してselectをテーブルに置き換えることはできないため、独立して行動します。



例としてdbTable_Userゲートウェイを解析します。 まず、selectメソッドをオーバーライドし、たとえばdbTable_User_Select(Zend_Db_Table_Selectの子孫)の内部でインスタンス化する必要があります。 次に、このクラスを開き、必要なメソッドを記述します。



クラスdbTable_User_SelectはZend_Db_Table_Selectを拡張します
 {
    パブリック関数ステータス($ステータス)
     { 
         return $ this-> where( 'status =?'、$ status);
     }
    公共機能性($性)
     {
         return $ this-> where( 'sex =?'、$ sex);
     }
    パブリック関数hasAvatar()
     {
         return $ this-> where( 'avatar is not null');
     }
    パブリック関数sortById()
     {
         return $ this-> order( 'id DESC);
     }
 }




それだけです! 使用できます。



  $ user_table-> select()-> hasAvatar()-> sex( 'male');
 $ user_table-> select()-> status( 'active')-> sortById();




メソッドを組み合わせることで、ほぼすべてのサンプルを作成できます。これらのマイクロメソッドのみをテストすれば十分です。



その結果、タイプSelectのオブジェクトを取得しました。データベースにリクエストを行うには、それらをゲートウェイのfetchRowまたはfetchAllに挿入する必要があります。 ここでもう一度チートを行い、すべてのdbTable_ ... _Select共通親を作成します。ここで次のメソッドを定義します。



 クラスExt_Db_Table_SelectはZend_Db_Table_Selectを拡張します
 {
    パブリック関数fetchRow()
     {
         return $ this-> getTable()-> fetchRow($ this);
     }

     public function fetchRowIfExists($ message = 'このページはサイトにありません')
     {
         return $ this-> getTable()-> fetchRowIfExists($ this、$ message);
     }

     public function fetchAll($ limit = null、$ offset = null)//最適なメソッド名ではありません)
     {
         if($ limit){
             $ this-> limit($ limit、$ offset);
         }

         return $ this-> getTable()-> fetchAll($ this);
     }

    パブリック関数getPaginator($ page = 1、$ limit = 10、$ pageRange = 7)
     {
         $ adapteree = new Ext_Paginator_AdapterAggregate($ this);
         $ paginator = Zend_Paginator :: factory($アダプタ);
         $ paginator-> setItemCountPerPage($ limit);
         $ paginator-> setCurrentPageNumber($ページ);
         $ paginator-> setPageRange($ pageRange);

         return $ paginator;
     }

     //これらの便利なメソッドも実装できます。
    パブリック関数カウント()
     public function max($ field){};
    パブリック関数min($フィールド){};
    パブリック関数の合計($フィールド){};
    パブリック関数が存在します(){};

     public function random($ limit = 5)//擬似ランダム
     {
         $ count = $ this-> count();
         $ offset =($ count> $ limit)?  $ count-$ limit:0;
         $ this-> limit($ limit、mt_rand(0、$ offset));

         return $ this-> fetchAll();
     }
 }




本質的に、selectはdbTableオブジェクトへのプロキシを開始し、dbTableオブジェクトは内部に格納します。 ボーナスとして、カウント、合計などの便利なメソッドがいくつかあります。 次に、結果から取得するために、これを行うために必要なものを選択します。



  $ select-> fetchRow();  //行を取得します
 $ select-> getPaginator($ページ);  //ページング
 $ select-> fetchAll(5);  // 5行かかります

 //多くの場合、空の結果で404をスローする必要がある場合に必要です
 $ select-> fetchRowIfExists();



All Articles