如何在Laravel项目首页展示每个Category下的最新Post?
如何在首页展示每个分类下的最新文章?
嘿,我来帮你搞定这个需求!先咱们先把基础的模型关联捋顺,然后给你两种实用的实现方式,你可以根据自己的场景选~
第一步:确保模型关联正确
首先,咱们得给Category和Post模型添加上关联方法,这是Laravel Eloquent处理关系的基础:
Category 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { // 一个分类对应多篇文章 public function posts() { return $this->hasMany(Post::class); } // 定义关联,直接获取该分类的最新文章 public function latestPost() { return $this->hasOne(Post::class)->latest(); } }
Post 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { // 一篇文章属于一个分类 public function category() { return $this->belongsTo(Category::class); } }
方法一:用Eloquent关联预加载(简洁直观)
这种方式最适合大多数场景,代码简洁,可读性强,还能避免N+1查询问题。
控制器代码
在你的首页控制器(比如HomeController)的index方法里,查询所有分类并预加载每个分类的最新文章:
public function index() { $categories = Category::with('latestPost')->get(); return view('home', compact('categories')); }
视图代码
在首页视图(比如resources/views/home.blade.php)里循环渲染分类和对应的最新文章:
@foreach($categories as $category) <div class="category-card"> <h3>{{ $category->name }}</h3> @if($category->latestPost) <div class="latest-post-item"> <h4>{{ $category->latestPost->title }}</h4> <!-- 截断文章内容,显示前100个字符 --> <p>{{ \Illuminate\Support\Str::limit($category->latestPost->body, 100) }}</p> @if($category->latestPost->image) <!-- 注意:要先执行php artisan storage:link创建存储软链接 --> <img src="{{ asset('storage/' . $category->latestPost->image) }}" alt="{{ $category->latestPost->title }}" class="post-image"> @endif </div> @else <p class="empty-tip">该分类还没有发布文章哦~</p> @endif </div> @endforeach
方法二:用查询构造器实现(灵活可控)
如果需要更复杂的筛选条件(比如只展示某些分类、排除特定状态的文章),可以用这种方式,直接通过数据库查询获取所有分类的最新文章。
控制器代码
public function index() { // 先获取每个分类下最新文章的ID(按created_at倒序取最新) $latestPostIds = Post::selectRaw('MAX(id) as post_id') ->groupBy('category_id') ->pluck('post_id'); // 根据ID集合获取对应的文章,并关联分类信息 $latestPosts = Post::with('category') ->whereIn('id', $latestPostIds) ->get(); // 把文章按分类分组,方便视图渲染 $postsByCategory = $latestPosts->groupBy('category_id'); return view('home', compact('postsByCategory')); }
视图代码
@foreach($postsByCategory as $categoryPosts) @php $category = $categoryPosts->first()->category @endphp <div class="category-card"> <h3>{{ $category->name }}</h3> @foreach($categoryPosts as $post) <div class="latest-post-item"> <h4>{{ $post->title }}</h4> <p>{{ \Illuminate\Support\Str::limit($post->body, 100) }}</p> @if($post->image) <img src="{{ asset('storage/' . $post->image) }}" alt="{{ $post->title }}" class="post-image"> @endif </div> @endforeach </div> @endforeach
小提示
- 如果想按
updated_at(更新时间)而不是created_at(创建时间)判断“最新”,只需要把latest()改成latest('updated_at')即可。 - 图片访问问题:如果你的
image字段存储的是本地文件路径,记得执行php artisan storage:link命令创建存储目录的软链接,否则前端无法访问图片。
内容的提问来源于stack exchange,提问作者user5565240
相关产品推荐
相关产品推荐

