Laravel中如何在URL显示名称而非ID并后台传递ID至控制器
在Laravel中用名称代替ID生成友好URL并获取对应ID的方案
这个需求其实很常见——想要更友好的URL,同时又不想暴露数据库ID,Laravel的路由模型绑定特性刚好能完美解决这个问题,下面一步步来实现:
1. 修改路由定义,指定绑定字段
首先把原来的路由参数从{id}改成{department:name}(这里department是你的模型名,name是你想在URL中显示的字段)。这样Laravel会自动根据传入的name值去查找对应的模型实例:
// routes/web.php use App\Http\Controllers\DepartmentController; use App\Models\Department; // 如果你用的是资源路由,可以这样指定参数字段 Route::resource('departments', DepartmentController::class)->parameters([ 'departments' => 'department:name' ]); // 或者单独定义单个路由 Route::get('/departments/{department:name}', [DepartmentController::class, 'show'])->name('departments.show');
2. 控制器中直接接收模型实例
在控制器的方法里,直接类型提示你的Department模型,Laravel会自动把匹配到的模型实例注入进来,你可以直接获取ID,完全不用自己去查数据库:
// app/Http/Controllers/DepartmentController.php namespace App\Http\Controllers; use App\Models\Department; class DepartmentController extends Controller { public function show(Department $department) { // 直接拿到对应模型的ID,比如这里就是3 $departmentId = $department->id; // 剩下的逻辑就和之前用ID的时候一样了 return view('departments.show', compact('department')); } }
3. 处理名称重复的问题(可选但推荐)
如果你的name字段可能存在重复(比如两个部门都叫"knee_pain"),那路由模型绑定会报错。这时候推荐用slug字段代替原始name:
- 首先在
departments表中添加一个slug字段,设置为唯一索引; - 在模型的
boot方法中,自动生成slug(比如把名称转成小写、替换特殊字符为横杠):
// app/Models/Department.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; class Department extends Model { protected static function boot() { parent::boot(); // 创建时自动生成slug static::creating(function ($department) { $department->slug = Str::slug($department->name); }); // 可选:更新名称时同步更新slug static::updating(function ($department) { if ($department->isDirty('name')) { $department->slug = Str::slug($department->name); } }); } }
然后把路由改成{department:slug},URL就会变成/departments/knee-pain(更符合URL规范),同时避免重复问题。
4. 生成正确的URL链接
在视图或者代码中生成URL的时候,直接传入模型实例即可,Laravel会自动使用你指定的字段(name或slug)生成正确的友好URL:
<!-- 视图中生成链接 --> <a href="{{ route('departments.show', $department) }}">查看部门</a>
这会生成类似/departments/knee_pain的链接,而不是带ID的版本。
内容的提问来源于stack exchange,提问作者raff
相关产品推荐
相关产品推荐

