You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何筛选与指定标签关联的所有文章?

实现Laravel博客按标签筛选文章功能

看起来你已经搭好了基础的表结构,接下来咱们一步步实现点击标签筛选文章的功能:

1. 补全关联表迁移

你提供的关联表代码没写完,这里补全完整的article_tag表迁移(注意要添加外键约束和联合主键,避免重复关联):

public function up() {
    Schema::create('article_tag', function (Blueprint $table) {
        $table->unsignedInteger('article_id');
        $table->unsignedInteger('tag_id');
        
        // 外键约束,删除文章/标签时自动删除关联记录
        $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
        $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
        
        // 设置联合主键,确保同一文章和标签不会重复关联
        $table->primary(['article_id', 'tag_id']);
    });
}

2. 定义模型多对多关联

Laravel的多对多关联需要在两个模型中分别定义关联方法:

Tag模型(app/Models/Tag.php)

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    // 允许批量赋值的字段
    protected $fillable = ['tags'];

    // 关联文章:一个标签对应多篇文章
    public function articles()
    {
        return $this->belongsToMany(Article::class);
    }
}

Article模型(app/Models/Article.php)

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    // 替换成你实际的文章字段
    protected $fillable = ['title', 'content', 'published_at'];

    // 关联标签:一篇文章对应多个标签
    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }
}

3. 添加路由

在routes/web.php中添加处理标签筛选的路由:

use App\Http\Controllers\TagController;

// 路由名称方便视图中生成链接
Route::get('/tags/{tag}', [TagController::class, 'show'])->name('tags.show');

4. 编写控制器逻辑

创建TagController并实现show方法,用于获取指定标签下的所有文章:

namespace App\Http\Controllers;

use App\Models\Tag;

class TagController extends Controller
{
    public function show(Tag $tag)
    {
        // 预加载文章数据,避免N+1查询问题
        $tag->load('articles');
        
        // 如果需要分页,改用下面的代码:
        // $articles = $tag->articles()->paginate(10);
        
        return view('tags.show', compact('tag'));
    }
}

5. 视图层实现

给标签添加跳转链接

在文章列表或详情页中,给每个标签加上跳转链接(比如articles/show.blade.php或articles/index.blade.php):

{{-- 遍历文章的所有标签 --}}
@foreach($article->tags as $tag)
    <a href="{{ route('tags.show', $tag) }}" class="inline-block px-3 py-1 bg-gray-100 rounded-full text-sm mr-2">
        {{ $tag->tags }}
    </a>
@endforeach

标签文章列表视图

创建resources/views/tags/show.blade.php,展示该标签下的所有文章:

<div class="container mx-auto px-4 py-8">
    <h1 class="text-2xl font-bold mb-6">标签: {{ $tag->tags }}</h1>

    <div class="space-y-6">
        @foreach($tag->articles as $article)
            <div class="border p-4 rounded-lg">
                <h2 class="text-xl font-semibold mb-2">
                    <a href="{{ route('articles.show', $article) }}" class="hover:text-blue-600">
                        {{ $article->title }}
                    </a>
                </h2>
                <p class="text-gray-700 mb-3">{{ Str::limit($article->content, 150) }}</p>
                <p class="text-sm text-gray-500">发布于 {{ $article->created_at->format('Y-m-d H:i') }}</p>
            </div>
        @endforeach

        {{-- 如果用分页,添加分页导航 --}}
        {{-- {{ $articles->links() }} --}}
    </div>
</div>

小建议

你的标签表字段名是tags,语义上有点奇怪,建议改成name更符合常规。如果已经建表,可以通过迁移修改:

public function up()
{
    Schema::table('tags', function (Blueprint $table) {
        $table->renameColumn('tags', 'name');
    });
}

修改后记得更新模型的$fillable和视图中的字段引用(把$tag->tags改成$tag->name)。

内容的提问来源于stack exchange,提问作者Brij Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:35:58