Laravel 5.1路由如何传递id与slug参数并生成规范URL?
解决URL带Slug时的路由匹配问题
看起来你遇到的核心问题是路由规则没有正确解析id和slug之间的分隔符,导致控制器无法获取到正确的文章ID,进而抛出“Trying to get property of non-object”错误。下面一步步帮你解决:
1. 修正路由定义
首先要确保你的路由能正确匹配/blog/{id}/{slug}的格式,同时让slug成为可选参数(毕竟你的控制器只需要ID查询数据)。假设你用的是Laravel框架,路由应该这样写:
// routes/web.php Route::get('blog/{id}/{slug?}', 'BlogController@show')->name('blog.show');
这里的{slug?}表示slug是可选参数,不管URL里有没有slug,路由都会正确提取前面的id值。
2. 生成规范的URL
在视图里生成URL时,要利用路由名称来构建,确保id和slug被正确拼接:
// 视图文件(比如blog/index.blade.php) <a href="{{ route('blog.show', [ 'id' => $post->id, 'slug' => Str::slug($post->title) // 用Str::slug生成标准化的slug ]) }}">{{ $post->title }}</a>
这样生成的URL就会是你想要的http://localhost:8000/blog/27/this-is-test-post格式。
3. 优化控制器逻辑
你的控制器只需要ID来获取数据,但可以额外做些优化:
// app/Http/Controllers/BlogController.php use Illuminate\Support\Str; use App\Models\Post; public function show($id, $slug = null) { // 用findOrFail替代find,找不到文章时直接返回404,避免null报错 $post = Post::findOrFail($id); // 可选:验证URL中的slug是否和文章标题匹配,防止用户篡改slug if ($slug && Str::slug($post->title) !== $slug) { return redirect()->route('blog.show', [ 'id' => $id, 'slug' => Str::slug($post->title) ]); } return view('blog.show', compact('post')); }
为什么之前会报错?
- 当你配置的路由是
Route::get('blog/{id}', ...)时,访问/blog/27/this-is-test-post会把27/this-is-test-post整个作为$id的值传递给控制器,用这个值去查询数据库自然找不到对应的文章,$post就会是null,视图里访问$post的属性就会抛出“Trying to get property of non-object”错误。 - 而访问
/blog/27this-is-test-post时,PHP会自动将字符串27this-is-test-post转换为整数27(因为你的ID是整数类型),所以控制器能查到正确的文章,也就不会报错——但这是不规范的写法,存在数据安全风险。
内容的提问来源于stack exchange,提问作者Brij Sharma
相关产品推荐
相关产品推荐

