如何比较cakephp 4.x中属于属性协会的查询条件?

发布于 2025-02-02 16:48:37 字数 4690 浏览 4 评论 0原文

我有一个有效的帖子,类别和标签关系。 (帖子属于属于类别和属于属于的标签。)它们在我的看法和索引动作中效果很好,没有问题。

现在,对于一个简单的“搜索”功能,我正在使用查询构建器。只要将术语与帖子和类别的字段进行比较,我设法成功地搜索了与我的查询有关的帖子,但是我也想让它与标签一起使用。

这是我的(工作)控制器:

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未知列'tags.name in in where子句'”错误。

如果我使用“ $ post-&gt; where(...)”我使用“ $ posts-&gt; find('all',['presenta'=&gt; [...]])):“也会发生同样的事情。选项。

所以我很困惑...如何在HABTM关系中搜索一个术语?

我想念什么?

I have a working Posts, Categories and Tags relationship. (Posts BelongsTo Categories and BelongsToMany Tags.) They work just fine at my view and index actions with no issue.

Now, for a simple "search" functionality I'm working with the Query builder. I managed to make it successfully search Posts related to my query, as long as the terms are compared to fields from Posts and Categories, but I would also want to make it work with Tags.

This is my (working) Controller:

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'));
}

These are my (working) Models:

// 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',
        ]);
    }
}

And this is my view:

<?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>

So when I submit the form, it filters my posts according to those conditions. But when I try adding a field from my Tags model to the search query, it breaks.

I tried adding the line:

['Tags.name LIKE' => '%'.$search.'%', 'Posts.status' => 'published']

...under:

['Categories.name LIKE' => '%'.$search.'%','Posts.status' => 'published']

But then when I introduce a query term, it throws me a "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Tags.name' in 'where clause'" error.

Same thing happens if instead of "$posts->where(...)" I use the "$posts->find('all',['conditions' => [...]]):" option.

So I'm stumped... How can I search a term within a HABTM relationship?

What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岛歌少女 2025-02-09 16:48:37

用户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'));
}

User ndm's comment did the trick. So in case it wasn't clear enough (and if someone ever finds the same issue I did in the future), here's my final working controller:

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'));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文