Laravel 7 新特性-路由的趟坑之路(自定义键名以及作用域)

作者: hedeqiang

发布时间: 2020-03-10 15:37:07

Laravel 7 开始新增了一些新特性,今天我们来讲解下 路由绑定的新用法,自定义键名(slug)以及作用域(范围限定)

首先我们 安装最新版本的 Laravel ,并且创建两张数据表。

安装 Laravel 7

composer create-project --prefer-dist laravel/laravel blog

生成用户认证脚手架

composer require laravel/ui

npm install && npm run dev

我们使用内置服务,来启动一个 web server

php artisan serve

生成用户填充数据

首先修改 .env 文件。修改数据库信息

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=root

注意:我这里使用 laradock ,所以 DB_HOSTmysql

新建 Post 文章数据表

php artisan make:model Post -mfcs

创建 Post 表字段,修改 database\migrations\日期_create_posts_table.php 文件

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->unsigned();
            $table->string('title');
            $table->text('body');
            $table->string('slug');
            $table->timestamps();
            $table->foreign('user_id')->references('id')->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

生成 数据表

php artisan migrate

添加 Post 数据工厂,修改 database\factories\PostFactory.php 文件

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Post;
use Faker\Generator as Faker;

$factory->define(Post::class, function (Faker $faker) {
    return [
        'user_id' => \App\User::all()->random(1)->first()->id,
        'title' => $faker->title,
        'body' => $faker->text,
        'slug' => $faker->slug,
    ];
});

用户数据填充

php artisan make:seed UsersTableSeeder
<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(\App\User::class,5)->create();
    }
}

Post 数据填充

<?php

use Illuminate\Database\Seeder;

class PostSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(\App\Post::class,50)->create();
    }
}

注册数据填充 database/seeds/DatabaseSeeder.php

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
         $this->call(UsersTableSeeder::class);
         $this->call(PostSeeder::class);
    }
}

运行迁移文件,进行数据填充

php artisan db:seed

ok,以上准备工作做完,(其实你大可不必这样,你可以任意创建 User、Post 数据表)我们正式开始今天的话题。

自定义键

首先我们来说一下自定义键是个什么东西,你可能知道,我们如果要查找一个数据,比如,我们要查询 Posts 文章表里的第一条数据。我们的以前的 URL 可能是如下这样:

http://laravel7.test/posts/posts/1

我们是通过主键 ID 来进行查找的。这种方法 看起来没什么问题,但是我们网站有多少数据用户是可以轻而易举地猜到。

当然我们在以前的版本可以更改这个,我们需要在 模型中重写一个方法 getRouteKeyName

接下来我们看下 Laravel 7 以前是怎么实现的

首先。定义一个路由

Route::get('posts/{post}', function (\App\Post $post) {
    dd($post);
});

接下来,我们重写 Post 模型文件 getRouteKeyName 方法。

public function getRouteKeyName()
{
    return 'slug';
}

接下来我们就可以使用 slug 来进行查询了 比如下面的 URL

http://laravel7.test/posts/amet-laudantium-reprehenderit-ullam-repudiandae

Laravel 7 的版本,实现以上自定义键,就更加方便了 只需要在 路由上添加一个动态参数即可。

Route::get('posts/{post:slug}', function (\App\Post $post) {
    dd($post);
});

作用域(访问限制)

怎么理解呢?举一个应用场景,我们要限定查找用户,然后在当前用户下查找他发表的文章某一篇文章。

我们代码演示一下

Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

首先 我们看下 数据库文章表的数据

file

假如我们查找文章 id 为 1,同时 他的 user_id 是 2, 那么访问的路由就是

http://laravel7.test/api/users/2/posts/1

file

那么我们在查找 id 为 2 的数据,可以看到 他的 user_id 并不是 2 了,理论上我们不应该查到才是。

http://laravel7.test/api/users/2/posts/2

然而实际情况确 并非如此。数据也是返回来了。

file

文档上就是这样呀?就是改变路由文件而已,照着做了,发现并不可以。

其实如果我们要实现如上的模式,我们还得需要设置模型的绑定关系

Post 模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

User 模型

public function posts()
{
    return $this->hasMany(Post::class);
}

OK,再试着访问下,纳尼,为什么还是可以访问到???

最终看了半天文档 我发现他给的路由后面有一个 动态参数 slug,加上试试。

Route::get('api/users/{user}/posts/{post:slug}', function (\App\User $user, \App\Post $post) {
    return $post;
});

那么 路由就得换成如下的方式:

http://laravel7.test/api/users/2/posts/et-saepe-enim-minus-et

这下终于可以了,终于实现我们想要的效果了。但是 难道非得是 slug 吗?我换成 id 不行吗?

Route::get('api/users/{user}/posts/{post:id}', function (\App\User $user, \App\Post $post) {
    return $post;
});

这样也是可以的。

好了,以上就是 Laravel 7 路由的新特性,外加我趟过的坑,希望对你有帮助。

关于极客返利

极客返利 是由我个人开发的一款网课返利、返现平台。包含 极客时间返现、拉勾教育返现、掘金小册返现、GitChat返现。目前仅包含这几个平台。后续如果有需要可以考虑其他平台。 简而言之就是:你买课,我返现。让你花更少的钱,就可以买到课程。

https://geek.laravelcode.cn

https://geek.idaka.ink

版权许可

本作品采用 知识共享署名 4.0 国际许可协议 进行许可。

转载无需与我联系,但须注明出处,注明文章来源 Laravel 7 新特性-路由的趟坑之路(自定义键名以及作用域)