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

Laravel框架下获取特定语言无对应翻译记录的Keyword数据的查询问题排查

问题排查与解决方案:筛选无指定语言翻译的Keyword数据

你当前的查询逻辑核心问题在于用错了关联检查方法:doesntHave('keywordsTranslated')是用来筛选完全没有任何翻译记录的Keyword,但你的需求是筛选没有对应指定language_id翻译记录的Keyword——这两个逻辑完全不同,这就是为什么返回结果不符合预期的原因。

正确的实现思路

你需要使用whereDoesntHave方法,它允许你给关联关系添加过滤条件,只筛选那些不存在满足特定条件的关联记录的主模型数据。具体来说,就是检查每个Keyword是否不存在language_id等于指定值的KeywordTranslated记录。

修改后的完整代码

public function searchTranslatedKeys(
    int $projectPageId,
    int $currentPage, // 修正原代码拼写错误:curentPage → currentPage
    int $languageId,
    string $search = null
) {
    $query = $this->model->newQuery();
    $query->where('project_page_id', $projectPageId);

    if ($search) {
        $query->where('key', 'LIKE', "%{$search}%");
    }

    // 关键修改:用whereDoesntHave替代doesntHave,添加language_id过滤条件
    $query->whereDoesntHave('keywordsTranslated', function ($q) use ($languageId) {
        $q->where('language_id', $languageId);
    });

    $query->orderBy('id', 'DESC');

    // 可选优化:建议用数据库层面分页替代内存分页(性能更优)
    if ($search) {
        return $query->get();
    }
    // 数据库分页写法(推荐):
    // return $query->skip(($currentPage - 1) * 20)->take(20)->get();
    // 或返回Laravel分页器对象:
    // return $query->paginate(20, ['*'], 'page', $currentPage);
    return $query->get()->forPage($currentPage, 20);
}

代码说明

  1. whereDoesntHave的作用:它会生成子查询,检查当前Keyword对应的keywordsTranslated关联中,是否不存在language_id = $languageId的记录,完全匹配你的需求:
    • 当language_id=2时,会筛选出没有language_id=2翻译的Keyword(id=2和3)
    • 当language_id=1时,会筛选出没有language_id=1翻译的Keyword(id=3)
  2. 拼写修正:原代码里的curentPage是拼写错误,修正为currentPage避免潜在bug
  3. 分页优化建议:原代码用get()->forPage是先拉取所有数据再内存分页,数据量大时性能很差。推荐换成数据库层面的分页(注释中的两种写法),直接在数据库中完成分页逻辑。

测试验证

用你的测试数据验证:

  • 当language_id=2时:Keyword1有对应翻译被排除,Keyword2、3无对应翻译被保留,返回2条数据
  • 当language_id=1时:Keyword1、2有对应翻译被排除,Keyword3无对应翻译被保留,返回1条数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:32:45