7、Laravel 11 模型查询

作者: 温新

图书: 【Laravel 11 构建 Web 应用与管理后台】

阅读: 384

时间: 2024-11-21 23:35:30

一般,发布的文章都有一个类型,而类型与文章之间又是一个一对多的关系,即一分类下可以有很多篇文章。本篇文章就来完善我们的 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 条件查询。不存在时就显示所有文章。

请登录后再评论