我正在使用CakePHP 1.3.8,并且安装了CakeDC搜索插件。我有一个教程模型,它与学习目标模型处于HABTM关系中。
我在教程控制器中有一个搜索操作和视图,通过它我可以成功搜索教程模型中的字段。我还想使用同一表单上的学习目标复选框过滤我的教程搜索结果。我尝试将各种参数添加到教程的$filterArgs和教程控制器的$presetVars。我还尝试将相关$filterArgs移动到学习目标模型。我尚未能够成功触发$filterArgs学习目标的条目。
我想我一定错过了一些明显的东西。或者,也许搜索插件不支持我正在尝试执行的操作。有谁知道如何使用此插件搜索相关模型?
这就是我想出的。您可以将以下内容与搜索插件说明相结合,以搜索相关模型。
教程模型中的$filterArgs部分必须如下所示:
var $filterArgs = array(
array('name' => 'LearningGoal', 'type' => 'subquery', 'method' => 'findByLearningGoals', 'field' => 'Tutorial.id'),
);
下面是教程模型中的支持函数:
function findByLearningGoals($data = array()) {
$ids = explode('|', $data['LearningGoal']);
$ids = join(',', $ids);
$this->LearningGoalsTutorial->Behaviors->attach('Containable', array('autoFields' => false));
$this->LearningGoalsTutorial->Behaviors->attach('Search.Searchable');
$query = $this->LearningGoalsTutorial->getQuery('all',
array(
'conditions' => array('LearningGoalsTutorial.learning_goal_id IN (' . $ids . ')'),
'fields' => array('tutorial_id'),
)
);
return $query;
}
在 TutorialsController 中,$presetVars应如下所示:
public $presetVars = array(
array('field' => 'LearningGoal', 'type' => 'checkbox', 'model' => 'Tutorial'),
);
在TutorialsController中的搜索操作中,我做到了:
$this->LearningGoal = $this->Tutorial->LearningGoal;
Prg 组件似乎需要这个。
我正在使用CakePHP版本2.X
每次我在项目中执行此操作时,我总是花费数小时弄清楚如何使用 CakeDC 搜索行为来做到这一点,所以我写这篇文章是为了尝试用简单的语言提醒自己我需要做什么。我还注意到,尽管Michael通常是正确的,但没有解释,这使得将其修改为自己的项目变得更加困难。
当您具有"具有并属于多个"关系并且想要搜索连接表时,即具有两个字段的表,该字段将多对多关系中两侧的表连接在一起,您希望创建一个子查询,其中包含关系中其中一个表中的 ID 列表。将检查关系另一端表中的 ID,以查看它们是否在该记录中,如果它们位于主表中,则将选择主表中的记录。
在以下示例中
SELECT Handover.id, Handover.title, Handover.description
FROM handovers AS Handover
WHERE Handover.id in
(SELECT ArosHandover.handover_id
FROM aros_handovers AS ArosHandover
WHERE ArosHandover.aro_id IN (3) AND ArosHandover.deleted != '1')
LIMIT 20
如果 ArosHandover 中的所有记录的aro_id为 3,则将选择它们,则 Handover.id 用于决定选择哪些移交记录。
关于如何使用 CakeDC 搜索行为执行此操作。
首先,将字段放入搜索表单中:
echo $this->Form->create('Handover', array('class' => 'form-horizontal'));?>
echo $this->Form->input('aro_id', array('options' => $roles, 'multiple' => true, 'label' => __('For', true), 'div' => false, true));
等。。。
请注意,我没有将表单元素放置在 ArosHandover 数据空间中;另一种说法是,当发送表单请求时,字段aro_id将被放置在名为 Handover 的数组下。
在变量 $filterArgs 下的模型中:
'aro_id' => array('name' => 'aro_id', 'type' => 'subquery', 'method' => 'findByAros', 'field' => 'Handover.id')
请注意,类型是"子查询",正如我上面提到的,您需要创建一个子查询才能找到适当的记录,并且通过将类型设置为子查询,您告诉 CakeDC 创建 SQL 的子查询片段。该方法是将在其下编写代码的函数名称。field 元素是将出现在上述示例查询的这一部分中的字段的名称
WHERE Handover.id in
然后编写将返回子查询的函数:
function findByAros($data = array())
{
$ids = ''; //you need to make a comma separated list of the aro_ids that are going to be checked
foreach($data['aro_id'] as $k => $v)
{
$ids .= $v . ', ';
}
if($ids != '')
{
$ids = rtrim($ids, ', ');
}
//you only need to have these two lines in if you have not already attached the behaviours in the ArosHandover model file
$this->ArosHandover->Behaviors->attach('Containable', array('autoFields' => false));
$this->ArosHandover->Behaviors->attach('Search.Searchable');
$query = $this->ArosHandover->getQuery('all',
array(
'conditions' => array('ArosHandover.aro_id IN (' . $ids . ')'),
'fields' => array('handover_id'), //the other field that you need to check against, it's the other side of the many-to-many relationship
'contain' => false //place this in if you just want to have the ArosHandover table data included
)
);
return $query;
}
在切换控制器中:
public $components = array('Search.Prg', 'Paginator'); //you can also place this into AppController
public $presetVars = true; //using $filterArgs in the model configuration
public $paginate = array(); //declare this so that you can change it
// this is the snippet of the search form processing
public function admin_find()
{
$this->set('title_for_layout','Find handovers');
$this->Prg->commonProcess();
if(isset($this->passedArgs) && !empty($this->passedArgs))
{//the following line passes the conditions into the Paginator component
$this->Paginator->settings = array('conditions' => $this->Handover->parseCriteria($this->passedArgs));
$handovers = $this->Paginator->paginate(); // this gets the data
$this->set('handovers', $handovers); // this passes it to the template
如果您想进一步解释我为什么做某事,请询问,如果我收到一封电子邮件告诉我您已经问过,我会在可能的情况下给出答案。