请教“查询已存在的关联”进行过滤并同时输出过滤后的和“不存在的关联”
运行环境
- CentOS Stream 9
- PHP 8.1.9
- Laravel v9.37.0
问题场景
一个 SNS 系统,涉及用户、屏蔽、帖子三个维度。在查询帖子时,希望过滤掉所属用户屏蔽话题的帖子。
模型
<?php
namespace App\Models;
class Post extends Model
{
public function hashtags()
{
return $this->belongsToMany(Hashtag::class, 'hashtag_usages', 'usage_id', 'hashtag_id')->wherePivot('usage_type', HashtagUsage::TYPE_POST)->wherePivot('deleted_at', null);
}
}
- posts 帖子表
- hashtags 话题表
- hashtag_usages 话题和帖子中间关联表(多对多,一个帖子有多个话题,一个话题也会有多个帖子)
问题
$postQuery = Post::with(['hashtags'])->latest();
// 用户屏蔽话题
$blockHashtagIds = [1,5,10]
if ($blockHashtagIds) {
$postQuery->whereHas('hashtags', function ($query) use ($blockHashtagIds) {
// 含有用户屏蔽话题的帖子不要
$query->whereNotIn('hashtag_id', $blockHashtagIds);
});
}
$posts = $postQuery->paginate(\request()->get('pageSize', 15));
使用whereHas
方法,模型只给我含有话题的帖子用于条件筛选,这样输出时不含话题的帖子也被过滤了。
问题原理:
- 你要过滤话题了,那我(框架)就只给你含有话题的帖子让你过滤,然后过滤后输出的就只有含话题的,因为不含话题的框架没有给我。
- 你要过滤小组了,那我(框架)就只给你含有小组的帖子让你过滤,小组 id 字段为 null 也不给你,因为你要过滤的
whereNotIn
是小组 id,它没有 id,所以不会在数据里(如果字段值为 0 我框架就给你数据,因为 0 也算是有小组的)。
求教
求教大神们,我应该如何实现,过滤掉含有屏蔽话题的帖子,其余(包括不含话题的帖子)都输出呢?
把
whereHas
改成whereDoesntHave
试试,并且whereNotIn
改成whereIn
应该是有两种方法实现的:
和一楼一样,使用
whereDoesntHave
还是使用
whereHas