我想查询关联的belongsToMany关系中的翻译。根据文档和this question,应该可以在翻译中查询关联。我尝试了以下(简化)代码:
$result = $this->table()->find()
->where([
$this->Activities->Tags->translationField('name') . ' LIKE' =>
'%' . $request->filter . '%'
])
->leftJoinWith('Tags')
->contain(['Tags'])
->all()
->toArray();
标签和活动有很多关系。
活动:
$this->belongsToMany('Tags', [
'foreignKey' => 'activity_id',
'targetForeignKey' => 'tag_id',
'joinTable' => 'activities_tags'
]);
$this->addBehavior('Translate', ['fields' => ['name', 'description']]);
标签:
$this->belongsToMany('Activities', [
'foreignKey' => 'tag_id',
'targetForeignKey' => 'activity_id',
'joinTable' => 'activities_tags'
]);
$this->addBehavior('Translate', ['fields' => ['name']]);
ActivityTag:
$this->belongsTo('Activities', [
'foreignKey' => 'activity_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Tags', [
'foreignKey' => 'tag_id',
'joinType' => 'INNER'
]);
但是,我得到以下生成的SQL:
SELECT
...
FROM `activities` `Activities`
LEFT JOIN `activities_tags` `ActivitiesTags` ON `Activities`.`id` = (`ActivitiesTags`.`activity_id`)
LEFT JOIN `tags` `Tags` ON `Tags`.`id` = (`ActivitiesTags`.`tag_id`)
LEFT JOIN `i18n` `Activities_name_translation` ON (
`Activities_name_translation`.`model` = :c0
AND `Activities_name_translation`.`field` = :c1
AND `Activities_name_translation`.`locale` = :c2
AND `Activities`.`id` = (`Activities_name_translation`.`foreign_key`)
)
LEFT JOIN `i18n` `Activities_description_translation` ON (
`Activities_description_translation`.`model` = :c3
AND `Activities_description_translation`.`field` = :c4
AND `Activities_description_translation`.`locale` = :c5
AND `Activities`.`id` = (`Activities_description_translation`.`foreign_key`)
)
WHERE `Tags_name_translation`.`content` like :c6
这导致我出现以下错误:
QLSTATE [42S22]:未找到列:1054未知列' Tags_name_translation.content'在' where子句'
缺少以下联接:
LEFT JOIN `i18n` `Tags_name_translation` ON (
`Tags_name_translation`.`model` = :c6
AND `Tags_name_translation`.`field` = :c7
AND `Tags_name_translation`.`locale` = :c8
AND `Tags`.`id` = (`Tags_name_translation`.`foreign_key`)
)
现在我的问题/编辑:
为了生成缺少的连接,我缺少什么来配置CakePHP?我的目的是通过翻译的标签过滤活动。它正在为非翻译工作。
答案 0 :(得分:1)
正如链接问题中所提到的,就像包含的hasMany
关联一样,belongsToMany
关联在单独的查询中被检索,这就是Translate行为将跳入并包含翻译关联的位置(每个字段由单独的hasOne
关联表示),以便将转换表加入。
对于*joinWith()
和*matching()
也是如此,而它将在主查询上应用连接和条件,实际关联内容及其相关翻译再次在单独的查询中检索,即转换行为不会涉及主查询,因此转换表没有被加入。有人可能称之为ORM的缺点,也许某种钩子加入/匹配在行为可以修改的情况下会有所帮助相应的查询,但现在没有这样的事情。
所以,没有过多的考虑,你可以使用相关的子查询(是的,我知道,它可能不会表现得太好)作为过滤条件,即通过{{1查询所需的标签表格,其中包含翻译,并在Tags
上使用EXISTS
条件,类似于以下内容:
Activities
可以看出,这将需要手动加入连接表($tagsQuery = $this->Activities->Tags
->find()
->select(['id'])
->innerJoinWith('ActivitiesTags')
->where(function (\Cake\Database\Expression\QueryExpression $exp) use ($request) {
return $exp
->equalFields('ActivitiesTags.activity_id', 'Activities.id')
->like(
$this->Activities->Tags->translationField('name'),
'%' . $request->filter . '%'
);
});
$activitiesQuery = $this->Activities
->find()
->where(function ($exp) use ($tagsQuery) {
return $exp->exists($tagsQuery);
});
)(在早期的CakePHP版本中,您可能需要手动添加该关联IIRC),以便您可以匹配{{1 }}。生成的查询应如下所示:
ActivitiesTags
最有可能解决此问题的其他方法,例如创建和包含其他翻译关联"手动"在ActivitiesTags.activity_id
时间。看看SELECT
`Activities`.`id` AS `Activities__id`, ...
FROM
`activities` `Activities`
WHERE
EXISTS (
SELECT
`Tags`.`id` AS `Tags__id`
FROM
`tags` `Tags`
INNER JOIN `activities_tags` `ActivitiesTags` ON
`Tags`.`id` = (`ActivitiesTags`.`tag_id`)
LEFT JOIN `i18n` `Tags_name_translation` ON (
`Tags_name_translation`.`model` = 'Tags'
AND `Tags_name_translation`.`field` = 'name'
AND `Tags_name_translation`.`locale` = 'en_US'
AND `Tags`.`id` = (`Tags_name_translation`.`foreign_key`)
)
WHERE
(
`ActivitiesTags`.`activity_id` = (`Activities`.`id`)
AND `Tags_name_translation`.`content` LIKE '%foobarbaz%'
)
)
和Model.beforeFind
的作用,您必须应用类似于TranslateBehavior::setupFieldAssociations()
表的内容才能实现此目标。