如何结合路由模型绑定在URL参数中使用可翻译字段?
解决Laravel多语言字段的路由模型绑定问题(无需显示ID)
核心思路
重写模型的resolveRouteBinding方法,让路由模型绑定能根据当前语言环境,查询JSON格式存储的多语言字段,无需额外添加slug字段或暴露ID。
步骤1:修改模型的路由绑定逻辑
针对Country和Province模型,分别添加以下代码:
Country模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Spatie\Translatable\HasTranslations; class Country extends Model { use HasTranslations; public $translatable = ['name']; // 重写路由绑定解析逻辑 public function resolveRouteBinding($value, $field = null) { if ($field === 'name') { // 根据当前语言查询JSON字段中的对应值 return $this->whereJsonContains("name->".app()->getLocale(), urldecode($value))->firstOrFail(); } return parent::resolveRouteBinding($value, $field); } }
Province模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Spatie\Translatable\HasTranslations; class Province extends Model { use HasTranslations; public $translatable = ['name']; // 重写路由绑定解析逻辑 public function resolveRouteBinding($value, $field = null) { if ($field === 'name') { return $this->whereJsonContains("name->".app()->getLocale(), urldecode($value))->firstOrFail(); } return parent::resolveRouteBinding($value, $field); } }
步骤2:保留原路由写法
原有路由代码无需修改,继续使用自定义键的路由模型绑定:
Route::get('/{country:name}/{province:name}', [AdminController::class, 'locations']);
优化:抽成Trait避免重复代码
如果多个模型需要处理多语言路由绑定,可将逻辑抽成Trait减少重复代码:
namespace App\Traits; trait TranslatableRouteBindingTrait { public function resolveRouteBinding($value, $field = null) { // 检查字段是否属于多语言属性 if (property_exists($this, 'translatable') && in_array($field, $this->translatable)) { return $this->whereJsonContains("{$field}->".app()->getLocale(), urldecode($value))->firstOrFail(); } return parent::resolveRouteBinding($value, $field); } }
之后在模型中直接使用该Trait即可:
class Country extends Model { use HasTranslations, TranslatableRouteBindingTrait; public $translatable = ['name']; }
补充说明
urldecode($value)用于处理URL中可能存在的编码字符(比如空格转成%20),确保查询匹配准确。- 该方案完全依赖已有的多语言JSON字段,无需修改数据库结构或添加额外逻辑。
- 访问对应语言的URL时(例如
/en/Canada/Ontario或/fr/Canada/Ontario),系统会自动根据当前语言环境查询匹配的模型。
内容的提问来源于stack exchange,提问作者Andrew Nelson
相关产品推荐
相关产品推荐

