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); }
代码说明
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)
- 当
- 拼写修正:原代码里的
curentPage是拼写错误,修正为currentPage避免潜在bug - 分页优化建议:原代码用
get()->forPage是先拉取所有数据再内存分页,数据量大时性能很差。推荐换成数据库层面的分页(注释中的两种写法),直接在数据库中完成分页逻辑。
测试验证
用你的测试数据验证:
- 当
language_id=2时:Keyword1有对应翻译被排除,Keyword2、3无对应翻译被保留,返回2条数据 - 当
language_id=1时:Keyword1、2有对应翻译被排除,Keyword3无对应翻译被保留,返回1条数据
内容的提问来源于stack exchange,提问作者GPiter
相关产品推荐
相关产品推荐

