Laravel多语言搜索问题:如何基于选中语言执行搜索
基于当前选中语言执行搜索的解决方案
针对你在Laravel项目中结合mcamara本地化扩展和搜索Scope的需求,我会根据常见的两种多语言存储结构给出具体实现方案:
情况1:使用独立翻译表(如news_translations)
如果你的多语言内容存在单独的翻译表(这是mcamara扩展的典型用法),可以通过关联查询翻译表来实现基于当前语言的搜索:
第一步:确保模型关联正确
在News模型中确认已定义与翻译模型的关联:
public function translations() { return $this->hasMany(NewsTranslation::class); }
第二步:修改搜索Scope
更新你的scopeSearch方法,加入当前语言的筛选条件,关联翻译表进行搜索:
public function scopeSearch($query, $searchTerm) { // 如果搜索词为空,直接返回原查询 if (empty(trim($searchTerm))) { return $query; } // 获取当前选中的语言 $currentLocale = app()->getLocale(); $lowerSearchTerm = strtolower($searchTerm); return $query->whereHas('translations', function ($subQuery) use ($currentLocale, $lowerSearchTerm) { $subQuery->where('locale', $currentLocale) ->where(function ($q) use ($lowerSearchTerm) { // 对标题和内容进行大小写不敏感的模糊搜索 $q->whereRaw('LOWER(title) LIKE ?', ["%{$lowerSearchTerm}%"]) ->orWhereRaw('LOWER(content) LIKE ?', ["%{$lowerSearchTerm}%"]); }); }); }
情况2:使用JSON字段存储多语言内容
如果你的多语言内容直接存在news表的JSON字段中(比如title和content字段是JSON类型,存储{"en": "xxx", "tr": "xxx"}这样的结构),可以直接查询JSON字段的对应语言键:
修改搜索Scope
public function scopeSearch($query, $searchTerm) { if (empty(trim($searchTerm))) { return $query; } $currentLocale = app()->getLocale(); $lowerSearchTerm = strtolower($searchTerm); return $query->where(function ($q) use ($currentLocale, $lowerSearchTerm) { // 使用MySQL的JSON函数查询对应语言的内容,同时做大小写不敏感处理 $q->whereRaw('LOWER(title->>?) LIKE ?', [$currentLocale, "%{$lowerSearchTerm}%"]) ->orWhereRaw('LOWER(content->>?) LIKE ?', [$currentLocale, "%{$lowerSearchTerm}%"]); }); }
额外注意事项
- SQL注入防护:上面的代码都使用了参数绑定(
?占位符),避免直接拼接搜索词导致的注入风险,一定要保持这种写法。 - 控制器调用:确保在控制器中获取当前语言时使用
app()->getLocale(),和你在Blade模板中切换语言的逻辑保持一致。 - 索引优化:如果你的数据量较大,建议给翻译表的
locale字段、title/content字段,或者JSON字段的对应语言键添加索引,提升搜索性能。
内容的提问来源于stack exchange,提问作者Ali Özen
相关产品推荐
相关产品推荐

