如何比较 CakePHP 4.x 中 BelongsToMany 关联的查询条件?
How to compare Query conditions from a BelongsToMany association in CakePHP 4.x?
我有一个有效的帖子、类别和标签关系。 (帖子 BelongsTo Categories 和 BelongsToMany 标签。)它们在我的视图和索引操作中工作得很好,没有问题。
现在,为了实现简单的“搜索”功能,我正在使用查询生成器。我设法让它成功搜索与我的查询相关的帖子,只要将术语与帖子和类别中的字段进行比较,但我也想让它与标签一起使用。
这是我的(工作)控制器:
public function search()
{
$search = $this->request->getQuery('query');
$posts = $this->Posts->find('all');
$posts->contain(['Categories','Tags']);
if(!empty($search)) {
$posts->where(['or' => [
['Posts.title LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Posts.content LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published'],
]]);
} else {
$posts->where(['Posts.status' => 'published']);
};
$posts = $this->paginate($posts);
$this->set(compact('posts'));
}
这些是我的(工作)模型:
// Posts Table
class PostsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('posts');
$this->setDisplayField('title');
$this->setPrimaryKey('id');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER',
]);
$this->belongsToMany('Tags',[
'foreignKey' => 'post_id',
'targetForeignKey' => 'tag_id',
'joinTable' => 'posts_tags'
]);
}
}
// Categories Table
class CategoriesTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('categories');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->hasMany('Posts', [
'foreignKey' => 'category_id',
]);
}
}
// Tags Table
class TagsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('tags');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsToMany('Posts', [
'foreignKey' => 'tag_id',
'targetForeignKey' => 'post_id',
'joinTable' => 'posts_tags',
]);
}
}
// PostsTags Table
class PostsTagsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('posts_tags');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Posts', [
'foreignKey' => 'post_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Tags', [
'foreignKey' => 'tag_id',
'joinType' => 'INNER',
]);
}
}
这是我的观点:
<?php $search = $this->request->getQuery('query'); ?>
<div class="posts index content">
<h1>Search Posts</h1>
<?= $this->Form->create(NULL,['type' => 'get']) ?>
<?= $this->Form->control('query',['default' => $search]) ?>
<?= $this->Form->button('submit') ?>
<?= $this->Form->end() ?>
<?php foreach ($posts as $post): ?>
<div class="card">
<!-- Here goes the Post data -->
</div>
<?php endforeach; ?>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(__('Page {{page}} of {{pages}}')) ?></p>
</div>
所以当我提交表单时,它会根据这些条件过滤我的帖子。但是当我尝试将我的标签模型中的字段添加到搜索查询时,它会中断。
我尝试添加以下行:
['Tags.name LIKE' => '%'.$search.'%', 'Posts.status' => 'published']
...在下:
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published']
但是当我引入一个查询词时,它抛出一个“SQLSTATE[42S22]:未找到列:1054 'where clause' 中的未知列 'Tags.name'”错误。
如果我使用“$posts->find('all',['conditions' => [.. .]]):" 选项。
所以我很困惑...如何在 HABTM 关系中搜索术语?
我错过了什么?
用户 ndm 的评论成功了。因此,以防万一它不够清楚(如果有人发现我以后遇到过同样的问题),这是我最终的工作控制器:
public function search()
{
$search = $this->request->getQuery('query');
$posts = $this->Posts->find('all')
->leftJoinWith('Tags')
->group(['Posts.id']);
$posts->contain(['Categories','Tags']);
if(!empty($search)) {
$posts->where(['or' => [
['Posts.title LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Posts.content LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published'],
['Tags.name LIKE' => '%'.$search.'%','Posts.status' => 'published']
]]);
} else {
$posts->where(['Posts.status' => 'published']);
};
$posts = $this->paginate($posts);
$this->set(compact('posts'));
}
我有一个有效的帖子、类别和标签关系。 (帖子 BelongsTo Categories 和 BelongsToMany 标签。)它们在我的视图和索引操作中工作得很好,没有问题。
现在,为了实现简单的“搜索”功能,我正在使用查询生成器。我设法让它成功搜索与我的查询相关的帖子,只要将术语与帖子和类别中的字段进行比较,但我也想让它与标签一起使用。
这是我的(工作)控制器:
public function search()
{
$search = $this->request->getQuery('query');
$posts = $this->Posts->find('all');
$posts->contain(['Categories','Tags']);
if(!empty($search)) {
$posts->where(['or' => [
['Posts.title LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Posts.content LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published'],
]]);
} else {
$posts->where(['Posts.status' => 'published']);
};
$posts = $this->paginate($posts);
$this->set(compact('posts'));
}
这些是我的(工作)模型:
// Posts Table
class PostsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('posts');
$this->setDisplayField('title');
$this->setPrimaryKey('id');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER',
]);
$this->belongsToMany('Tags',[
'foreignKey' => 'post_id',
'targetForeignKey' => 'tag_id',
'joinTable' => 'posts_tags'
]);
}
}
// Categories Table
class CategoriesTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('categories');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->hasMany('Posts', [
'foreignKey' => 'category_id',
]);
}
}
// Tags Table
class TagsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('tags');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsToMany('Posts', [
'foreignKey' => 'tag_id',
'targetForeignKey' => 'post_id',
'joinTable' => 'posts_tags',
]);
}
}
// PostsTags Table
class PostsTagsTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('posts_tags');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Posts', [
'foreignKey' => 'post_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Tags', [
'foreignKey' => 'tag_id',
'joinType' => 'INNER',
]);
}
}
这是我的观点:
<?php $search = $this->request->getQuery('query'); ?>
<div class="posts index content">
<h1>Search Posts</h1>
<?= $this->Form->create(NULL,['type' => 'get']) ?>
<?= $this->Form->control('query',['default' => $search]) ?>
<?= $this->Form->button('submit') ?>
<?= $this->Form->end() ?>
<?php foreach ($posts as $post): ?>
<div class="card">
<!-- Here goes the Post data -->
</div>
<?php endforeach; ?>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(__('Page {{page}} of {{pages}}')) ?></p>
</div>
所以当我提交表单时,它会根据这些条件过滤我的帖子。但是当我尝试将我的标签模型中的字段添加到搜索查询时,它会中断。
我尝试添加以下行:
['Tags.name LIKE' => '%'.$search.'%', 'Posts.status' => 'published']
...在下:
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published']
但是当我引入一个查询词时,它抛出一个“SQLSTATE[42S22]:未找到列:1054 'where clause' 中的未知列 'Tags.name'”错误。
如果我使用“$posts->find('all',['conditions' => [.. .]]):" 选项。
所以我很困惑...如何在 HABTM 关系中搜索术语?
我错过了什么?
用户 ndm 的评论成功了。因此,以防万一它不够清楚(如果有人发现我以后遇到过同样的问题),这是我最终的工作控制器:
public function search()
{
$search = $this->request->getQuery('query');
$posts = $this->Posts->find('all')
->leftJoinWith('Tags')
->group(['Posts.id']);
$posts->contain(['Categories','Tags']);
if(!empty($search)) {
$posts->where(['or' => [
['Posts.title LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Posts.content LIKE' => '%'.$search.'%', 'Posts.status' => 'published'],
['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published'],
['Tags.name LIKE' => '%'.$search.'%','Posts.status' => 'published']
]]);
} else {
$posts->where(['Posts.status' => 'published']);
};
$posts = $this->paginate($posts);
$this->set(compact('posts'));
}