2012-01-04 3 views
2

で、私はこの関係がない:改ページはhasOneのでは動作しますが、たとえば、hasManyの

UserContact hasMany Contact 
Contact hasOne Info 
Contact hasMany Response 

をそして、私は連絡先をページ付けする必要があるので、私は収容可能使用:

$this->paginate = array(
      'limit'=>50, 
      'page'=>$page, 
      'conditions' =>array('Contact.id'=>$id), 
      'contain'=>array(
       'Response', 
       'Info' 
       ) 
      ); 

I Info.nameとResponse.descriptionで検索を追加したいInfo.nameで完璧に動作しますが、Response.descriptionを使用しようとするとエラーが発生し、その列は存在しません。

さらに、Contact hasOne Responseとの関係を変更してから、正しくフィルタリングしましたが、最初の応答のみが返されますが、これは正しい関係ではありません。

私は、検索キー$フィルターを持っているのであれば、例えば、私は唯一のマッチングInfo.nameまたはResponse.descriptionに一致する少なくとも1つを有していて、それらの連絡先を返すようにしたいと思います。

答えて

3

あなたはCakePHPが、あなたはそれがメインクエリでの句に参加として含まれる「シングル」の関係(hasOnebelongsTo)を生成していることがわかりますSQLクエリを構築し、それが含まれている「複数」の関係のために別々のクエリを追加する方法を見ている場合。

これは、関連モデルのテーブルがすでにメインクエリで結合されているため、単一の関係によるフィルタリングを簡単にします。

あなたはサブクエリを作成する必要があります複数の関係によってフィルタリングするために:

// in contacts_controller.php: 
$conditionsSubQuery = array(
    'Response.contact_id = Contact.id', 
    'Response.description LIKE' => '%'.$filter.'%' 
); 
$dbo = $this->Contact->getDataSource(); 
$subQuery = $dbo->buildStatement(array(
    'fields' => array('Response.id'), 
    'table' => $dbo->fullTableName($this->Contact->Response), 
    'alias' => 'Response', 
    'conditions' => $conditionsSubQuery 
), $this->Contact->Response); 
$subQuery = ' EXISTS (' . $subQuery . ') '; 

$records = $this->paginate(array(
    'Contact.id' => $id, 
    $dbo->expression($subQuery) 
)); 

しかし、あなたはResponseフィールドでフィルタする必要がある場合にのみサブクエリを生成する必要があり、そうでなければ、フィルタリングします応答のない連絡先を削除します。

PS。このコードは、コントローラに表示するには大きすぎ、醜いです。各モデルは、独自のサブクエリを生成することができるように、私は、app_model.phpにそれをリファクタリング私のプロジェクトの場合:

function makeSubQuery($wrap, $options) { 
    if (!is_array($options)) 
     return trigger_error('$options is expected to be an array, instead it is:'.print_r($options, true), E_USER_WARNING); 
    if (!is_string($wrap) || strstr($wrap, '%s') === FALSE) 
     return trigger_error('$wrap is expected to be a string with a placeholder (%s) for the subquery. instead it is:'.print_r($wrap, true), E_USER_WARNING); 

    $ds = $this->getDataSource(); 

    $subQuery_opts = array_merge(array(
     'fields' => array($this->alias.'.'.$this->primaryKey),   
     'table' => $ds->fullTableName($this),   
     'alias' => $this->alias, 
     'conditions' => array(),  
     'order' => null, 
     'limit' => null, 
     'index' => null, 
     'group' => null 
    ), $options); 

    $subQuery_stm = $ds->buildStatement($subQuery_opts, $this); 
    $subQuery = sprintf($wrap, $subQuery_stm); 
    $subQuery_expr = $ds->expression($subQuery); 
    return $subQuery_expr; 
} 

次に、あなたのコントローラ内のコードは次のようになります。

$conditionsSubQuery = array(
    'Response.contact_id = Contact.id', 
    'Response.description LIKE' => '%'.$filter.'%' 
); 
$records = $this->paginate(array(
    'Contact.id' => $id, 
    $this->Contact->Response->makeSubQuery('EXISTS (%s)', array('conditions' => $conditionsSubQuery)) 
)); 
+0

すごくいいですね!私は間違いなく(賞金の有効期限が切れる前の)翌日にショットを与え、あなたに知らせるでしょう。 –

+0

私は実際に複数のものを同時に検索する必要があるので、今回はこのコードを使用しません。レスポンスなしで連絡先を削除すると問題が発生します。それにもかかわらず、答えは正しいです(ケーキの方法はありません)。提供されたコードは間違いなく別の状況で便利になるので、私はあなたに賞金をあげます。ありがとう! –

0

私は今試すことはできませんが、連絡先モデルではなく応答モデルに改ページを行うとうまくいくはずです。

+0

ページネーションが、その後動作しますが、しないだろう私は何が必要です。私はすべての連絡先(連絡先別にグループ化された回答を持つ)にページ番号が必要です。 –

関連する問題