7、Laravel 11 模型查询
一般,发布的文章都有一个类型,而类型与文章之间又是一个一对多的关系,即一分类下可以有很多篇文章。本篇文章就来完善我们的 Bolg。
文章迁移文件
1、创建文章迁移文件
$ php artisan make:migration "craete posts table"
2、编写迁移文件
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('category_id')->default(0)->index()->comment('分类 ID');
            $table->string('title')->index()->comment('文章标题');
            $table->text('text')->comment('文章内容');
            $table->timestamps();
        });
    }
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};
3、执行迁移文件
$ php artisan migrate
为了接下来的效果演示,请大家收手动为文章表添加一些数据吧。
模型查询
1、创建模型
$ php artisan make:model Post
2、控制器获取文章
app/Http/Controllers/HomeController.php
<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Models\Post;
class HomeController extends Controller
{
    public function index()
    {
        // 分类
        $categories = Category::all();
        // 获取所有文章
        $posts = Post::latest()->get();
        return view('home', compact('categories', 'posts'));
    }
}
3、视图显示文章
resources/views/home.blade.php
@extends('layouts.app')
@section('content')
    <!-- Page header with logo and tagline-->
    <header class="py-5 bg-light border-bottom mb-4">
        <div class="container">
            <div class="text-center my-5">
                <h1 class="fw-bolder">一方天地!</h1>
                <p class="lead mb-0">嗨,我是王美丽</p>
            </div>
        </div>
    </header>
    <div class="container">
        <div class="row">
            <!-- Blog entries-->
            <div class="col-lg-8">
                <!-- Nested row for non-featured blog posts-->
                <div class="row">
                    @foreach($posts as $post)
                        <div class="col-lg-6">
                            <!-- Blog post-->
                            <div class="card mb-4">
                                <a href="#!"><img class="card-img-top" src="https://dummyimage.com/700x350/dee2e6/6c757d.jpg" alt="..." /></a>
                                <div class="card-body">
                                    <div class="small text-muted">{{ $post->created_at }}</div>
                                    <h2 class="card-title h4">{{ $post->title }}</h2>
                                    <p class="card-text">{{ $post->text }}</p>
                                    <a class="btn btn-primary" href="#!">Read more →</a>
                                </div>
                            </div>
                        </div>
                    @endforeach
                </div>
                <!-- Pagination-->
                <nav aria-label="Pagination">
                    <hr class="my-0" />
                    <ul class="pagination justify-content-center my-4">
                        <li class="page-item disabled"><a class="page-link" href="#" tabindex="-1" aria-disabled="true">Newer</a></li>
                        <li class="page-item active" aria-current="page"><a class="page-link" href="#!">1</a></li>
                        <li class="page-item"><a class="page-link" href="#!">2</a></li>
                        <li class="page-item"><a class="page-link" href="#!">3</a></li>
                        <li class="page-item disabled"><a class="page-link" href="#!">...</a></li>
                        <li class="page-item"><a class="page-link" href="#!">15</a></li>
                        <li class="page-item"><a class="page-link" href="#!">Older</a></li>
                    </ul>
                </nav>
            </div>
            <!-- Side widgets-->
            <div class="col-lg-4">
                <!-- Search widget-->
                <div class="card mb-4">
                    <div class="card-header">Search</div>
                    <div class="card-body">
                        <div class="input-group">
                            <input class="form-control" type="text" placeholder="Enter search term..." aria-label="Enter search term..." aria-describedby="button-search" />
                            <button class="btn btn-primary" id="button-search" type="button">Go!</button>
                        </div>
                    </div>
                </div>
                <!-- Categories widget-->
                <div class="card mb-4">
                    <div class="card-header">Categories</div>
                    <div class="card-body">
                        <div class="row">
                            <div class="col-sm-6">
                                <ul class="list-unstyled mb-0">
                                    @foreach($categories as $category)
                                        <li><a href="#!">{{ $category->name }}</a></li>
                                    @endforeach
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- Side widget-->
                <div class="card mb-4">
                    <div class="card-header">Side Widget</div>
                    <div class="card-body">You can put anything you want inside of these side widgets. They are easy to use, and feature the Bootstrap 5 card component!</div>
                </div>
            </div>
        </div>
    </div>
@endsection
我们的文章就已经成功渲染了出来。浏览器看看效果吧。
根据分类显示文章
我们已经完成了文章的显示,不过,获取的是所有文章。下面,我们为文章添加一个过滤的功能,按照文章类型进行搜索。
1、修改视图文件
resources/views/home.blade.php
...
<!-- Categories widget-->
<div class="card mb-4">
    <div class="card-header">Categories</div>
    <div class="card-body">
        <div class="row">
            <div class="col-sm-6">
                <ul class="list-unstyled mb-0">
                    @foreach($categories as $category)
                        <li><a href="{{ route('home') }}?category_id={{ $category->id }}">{{ $category->name }}</a></li>
                    @endforeach
                </ul>
            </div>
        </div>
    </div>
</div>
...
2、控制器中进行搜索
app/Http/Controllers/HomeController.php
...
public function index()
{
	...
        
    // 获取所有文章
    $posts = Post::where('category_id', request('category_id'))->latest()->get();
	
    ...
}
...
此时,就已经可以访问了,请先按照下面的顺序进行访问:
- 
http://b-laravel11-blog.test/ - 
http://b-laravel11-blog.test/?category_id=1 
此时,应该会发现问题了,当不传递 category_id 参数时,获取不到数据。
3、默认显示所有文章
由此,我们会想到一个方法,当不传递 category_id 参数时,就默认显示所有文章。在 Laravel 中,我们可以使用 when 方法来实现。
app/Http/Controllers/HomeController.php
...
public function index()
{
	...
    // 获取所有文章
    $posts = Post::when(request('category_id'), function ($query) {
        $query->where('category_id', request('category_id'));
    })->latest()->get();
	
    ...
}
...
使用 when 方法时,当请求中 category_id 存在时,才会去执行 where 条件查询。不存在时就显示所有文章。
请登录后再评论