You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中基于其他模型记录过滤数据(实现用户拉黑功能)

问题分析与解决方案

原代码逻辑方向错误,导致无法过滤拉黑关系的用户。whereDoesntHave('blocklist', ...) 是检查待查询用户的拉黑记录(即该用户作为拉黑者的blocklist条目),但你传入的条件是user_id = auth()->id(),这和需求完全不符,因此会返回所有用户。

以下是两种可行的修复方案:


方法一:直接用子查询排除目标用户

通过两个子查询分别过滤掉「当前用户拉黑的用户」和「拉黑当前用户的用户」:

use App\Models\User;
use Illuminate\Support\Facades\Auth;

$currentUserId = Auth::guard('sanctum')->id();

$users = User::query()
    // 排除当前用户拉黑的用户
    ->whereNotIn('id', function ($query) use ($currentUserId) {
        $query->select('blockable_id')
            ->from('blocklist')
            ->where('user_id', $currentUserId)
            ->where('blockable_type', User::class);
    })
    // 排除拉黑当前用户的用户
    ->whereNotIn('id', function ($query) use ($currentUserId) {
        $query->select('user_id')
            ->from('blocklist')
            ->where('blockable_id', $currentUserId)
            ->where('blockable_type', User::class);
    })
    ->get();

方法二:优化模型关联后使用whereDoesntHave

先在User模型中添加两个语义化关联,让查询更清晰:

// app/Models/User.php
use App\Models\Blocklist;

// 自己拉黑的用户
public function blockedUsers()
{
    return $this->hasManyThrough(
        User::class,
        Blocklist::class,
        'user_id',          // Blocklist表中关联当前用户的字段(拉黑者ID)
        'id',               // 被拉黑用户表的主键
        'id',               // 当前用户表的主键
        'blockable_id'      // Blocklist表中关联被拉黑用户的字段
    )->where('blocklist.blockable_type', User::class);
}

// 拉黑自己的用户
public function blockedByUsers()
{
    return $this->hasManyThrough(
        User::class,
        Blocklist::class,
        'blockable_id',     // Blocklist表中关联当前用户的字段(被拉黑者ID)
        'id',               // 拉黑者用户表的主键
        'id',               // 当前用户表的主键
        'user_id'           // Blocklist表中关联拉黑者的字段
    )->where('blocklist.blockable_type', User::class);
}

然后在控制器中通过关联过滤:

$currentUser = Auth::guard('sanctum')->user();

$users = User::query()
    // 排除被当前用户拉黑的用户
    ->whereDoesntHave('blockedByUsers', fn($query) => $query->where('users.id', $currentUser->id))
    // 排除拉黑当前用户的用户
    ->whereDoesntHave('blockedUsers', fn($query) => $query->where('users.id', $currentUser->id))
    ->get();

内容的提问来源于stack exchange,提问作者3m1n3nc3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:00:26