Laravel如何在博客readmore链接中用标题代替ID访问单页
问题解决方法
你遇到的报错核心原因是Blog::find($title)逻辑错误:find()方法默认匹配模型主键(通常是id字段),传入标题字符串无法查询到对应博客记录,返回null,视图中调用空值的image属性就触发了「非对象取属性」的错误。
按照以下步骤修改即可实现标题/别名作为路由参数访问的需求:
1. 临时修正基础报错
先修改控制器的查询逻辑,同时补全缺失的评论、回复查询代码(你原有代码中$blogcomments、$blogreplies未定义,视图调用也会报错):
public function showblog($title) { // 用where匹配title字段,查不到直接返回404,避免空对象 $blog = Blog::where('title', $title)->firstOrFail(); // 补全评论、回复查询逻辑,对应替换成你实际的关联模型名 $blogcomments = BlogComment::where('blog_id', $blog->id)->get(); $blogreplies = BlogReply::whereIn('comment_id', $blogcomments->pluck('id'))->get(); return view('edific.show-blog', compact('blog', 'blogcomments', 'blogreplies')); }
如果你的标题包含中文、空格、特殊符号,需要给路由加参数正则规则,避免被Laravel默认路由规则拦截:
Route::get('/blog/{title}', 'EdificController@showblog')->where('title', '.*');
2. 推荐优化方案(解决URL乱码、标题重复问题)
直接用原生标题作为URL参数会出现乱码、重复标题匹配错误的问题,推荐新增slug字段存储唯一的URL友好别名:
2.1 新增字段
创建迁移文件:
php artisan make:migration add_slug_to_blogs_table
编辑迁移文件内容:
public function up() { Schema::table('blogs', function (Blueprint $table) { $table->string('slug')->unique()->after('title'); }); }
执行迁移:
php artisan migrate
2.2 生成别名
新增/编辑博客时,用Str::slug()方法生成URL友好的别名(中文标题可以搭配拼音扩展包生成拼音别名),存入slug字段,保证每个别名全局唯一。
2.3 修改路由和查询逻辑
修改单篇博客路由,推荐加路由别名避免硬编码URL:
Route::get('/blog/{slug}', 'EdificController@showblog')->name('blog.show');
修改控制器查询逻辑:
public function showblog($slug) { $blog = Blog::where('slug', $slug)->firstOrFail(); $blogcomments = BlogComment::where('blog_id', $blog->id)->get(); $blogreplies = BlogReply::whereIn('comment_id', $blogcomments->pluck('id'))->get(); return view('edific.show-blog', compact('blog', 'blogcomments', 'blogreplies')); }
修改列表页跳转链接:
<a href="{{ route('blog.show', $blog->slug) }}" class="post-meta">Read More</a>
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

