我2天前写过关于andConditions的问题,似乎我不明白这个想法,但事实是两天后我现在仍然坚持使用CakeDC的下一步:
如何在CakeDC搜索插件的“查询”方法中实现复杂的HABTM条件?
我提供HABTM功能(表格:优惠,功能,功能_offers),以下工作在控制器中使用时效果很好:
debug($this->Offer->find('all', array('contain' => array(
'Feature' => array(
'conditions' => array(
'Feature.id in (8, 10)',
)
)
)
)
)
);
当我想在搜索中使用相同的条件时出现问题:
public $filterArgs = array(
array('name' => 'feature_id', 'type' => 'query', 'method' => 'findByFeatures'),
);
........
public function findByFeatures($data = array()) {
$conditions = '';
$featureID = $data['feature_id'];
if (isset($data['feature_id'])) {
$conditions = array('contain' => array(
'Feature' => array(
'conditions' => array(
'Feature.id' => $data['feature_id'],
)
)
)
);
}
return $conditions;
}
我收到错误:
错误:SQLSTATE [42S22]:找不到列:1054未知列 'where子句'中包含'contains'
这让我觉得我无法在搜索中执行此搜索和/或使用可包含的行为。
如果我在该领域有更多经验的人,请告诉我,如果我遗漏了某些东西或指出我到底在哪里寻找解决方案 - 也许是食谱中的一个部分?
编辑:还试过加入。这在控制器中工作得很好,返回了我需要的所有数据:$options['joins'] = array(
array('table' => 'features_offers',
'alias' => 'FeaturesOffers',
'type' => 'inner',
'conditions' => array(
'Offer.id = FeaturesOffers.offer_id'
),
array('table' => 'features',
'alias' => 'F',
'type' => 'inner',
'conditions' => array(
'F.id = FeaturesOffers.feature_id'
),
)
),
);
$options['conditions'] = array(
'feature_id in (13)' //. $data['feature_id']
);
debug($this->Offer->find('all', $options));
...当我尝试输入搜索方法时,我只在SQL的where子句中获取返回的条件
WHERE((joins =(Array))AND(conditions =('array'中的'feature_id)))
...导致错误:
编辑:也许我很愚蠢而且很遗憾地说,但插件的文档很糟糕。SQLSTATE [42S22]:找不到列:1054'where子句'中的未知列'加入'
我检查了双倍,三倍和四倍(顺便说一句,至少在搜索表单的一个字段中已经丢失了30个小时 facepalm )并且文档中的愚蠢findByTags仍然没有任何意义对我来说。
public function findByTags($data = array()) {
$this->Tagged->Behaviors->attach('Containable', array('autoFields' => false));
$this->Tagged->Behaviors->attach('Search.Searchable');
$query = $this->Tagged->getQuery('all', array(
'conditions' => array('Tag.name' => $data['tags']),
'fields' => array('foreign_key'),
'contain' => array('Tag')
));
return $query;
}
据我了解
$this->Tagged
应该是HABTM协会模型的名称。
这与cakePHP的标准相差甚远:http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm
这里描述的方式说,你不需要另一个模型,而是将Recipe与Ingredient相关联,如下所示:
class Recipe extends AppModel {
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
意味着您可以从Recipe访问HABTM关联表数据,而无需定义模型“IngredientRecipe”。
根据cakeDC文档,您需要的模型是IngredientRecipe,并且未在cakePHP文档中指明为必需的。即使创建了这个模型,HABTM assoc也无法正常使用它 - 我也试过了。
现在我需要以我的方式重新编写搜索功能,只使用cakePHP,即使我已经花了30个小时......所以不开心。 :(
答案 0 :(得分:1)
每次我在一个项目中这样做时,我总是花费数小时来弄清楚如何使用CakeDC搜索行为来做到这一点,所以我写这篇文章试图用简单的语言提醒自己我需要做什么。我也注意到虽然Using the CakeDC search plugin with associated models这通常是正确的,但是没有任何解释使得将它修改为一个人自己的项目变得更加困难。
如果你有一个“拥有并且属于许多”的关系,并且你想要搜索连接表,即其中包含两个字段的表,它们将它们的两侧的表连接在一起许多关系,您希望创建一个子查询,其中包含关系中其中一个表的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
如果AroHandover的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
如果你想进一步解释为什么我做了什么,请问,如果我收到一封电子邮件,告诉我你已经问过,如果我能够,我会给出答案。
答案 1 :(得分:0)
这不是插件的问题,而是如何构建关联。您需要正确加入它们以搜索这三个表。检查CakePHP默认情况下如何从HABTM关联中获取数据。
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
假设Book hasAndBelongsToMany Tag关联。这种关系使用 books_tags表作为连接表,因此您需要加入books表 到books_tags表,这与标签表:
$options['joins'] = array(
array('table' => 'books_tags',
'alias' => 'BooksTag',
'type' => 'inner',
'conditions' => array(
'Books.id = BooksTag.books_id'
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'inner',
'conditions' => array(
'BooksTag.tag_id = Tag.id'
)
)
);
$options['conditions'] = array(
'Tag.tag' => 'Novel'
);
$ books = $ Book-> find('all',$ options);使用连接可以让你拥有 CakePHP处理关联和获取的最大灵活性 数据,但在大多数情况下,您可以使用其他工具来实现 相同的结果,如正确定义关联,绑定模型 在运行中并使用Containable行为。这个功能应该是 小心使用,因为在某些情况下,它可能导致形成不良 SQL查询是否与任何前面描述的技术结合使用 用于关联模型。
你的代码也错了。
Column not found: 1054 Unknown column 'contain' in 'where clause'
这意味着以某种方式调用$ Model-> contains()。我在你的代码中没有看到这样的调用,所以它必须在其他地方。如果找不到模型方法,则通常会将字段名称作为列发生此错误。
答案 2 :(得分:0)
我想与大家分享使用插件处理HABTM搜索的解决方案:Using the CakeDC search plugin with associated models
@burzum,文档远非好人。你注意到使用'type'=> '复选框'并且在任何地方都没有提到它是一种类型? 更不用说完全缺乏语法和大量的错别字和缺少介词。我失去了2天只是为了弄清楚作者的想法并将那些词绑在那里。没有评论。
我很高兴在上坡工作5天后我做到了。无论如何,谢谢您的帮助。