如果您看看CakePHP如何構建SQL查詢,您會看到它生成包含的「單個」關係(hasOne
和belongsTo
)作爲主查詢中的連接子句,然後它爲包含的「多個」關係添加單獨的查詢。
這使得通過單一關係進行篩選變得輕而易舉,因爲相關模型的表已經加入到主查詢中。
爲了用倍數關係來過濾你必須創建一個子查詢:
// 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))
));
這看起來不錯!我肯定會在接下來的幾天裏(在賞金到期之前)出手,並且讓你知道。 – 2012-01-09 12:33:47
結果我不會使用這段代碼,因爲我實際上需要同時搜索多件事情,所以刪除沒有響應的聯繫人將導致問題。儘管如此,答案是正確的(沒有蛋糕的方式),所提供的代碼在另一種情況下肯定會派上用場,所以我會獎勵你的賞金。謝謝! – 2012-01-12 18:00:08