Laravel 7 开始新增了一些新特性,今天我们来讲解下 路由绑定的新用法,自定义键名(slug)以及作用域(范围限定)
首先我们 安装最新版本的 Laravel ,并且创建两张数据表。
安装 Laravel 7
代码语言:javascript复制composer create-project --prefer-dist laravel/laravel blog
生成用户认证脚手架
代码语言:javascript复制composer require laravel/ui
npm install && npm run dev
我们使用内置服务,来启动一个 web server
代码语言:javascript复制php artisan serve
生成用户填充数据
首先修改 .env 文件。修改数据库信息
代码语言:javascript复制DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=root
注意:我这里使用 laradock ,所以
DB_HOST
为mysql
新建 Post 文章数据表
代码语言:javascript复制php artisan make:model Post -mfcs
创建 Post 表字段,修改 databasemigrations日期_create_posts_table.php
文件
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
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');
}
}
生成 数据表
代码语言:javascript复制php artisan migrate
添加 Post 数据工厂,修改 databasefactoriesPostFactory.php
文件
<?php
/** @var IlluminateDatabaseEloquentFactory $factory */
use AppPost;
use FakerGenerator as Faker;
$factory->define(Post::class, function (Faker $faker) {
return [
'user_id' => AppUser::all()->random(1)->first()->id,
'title' => $faker->title,
'body' => $faker->text,
'slug' => $faker->slug,
];
});
用户数据填充
代码语言:javascript复制php artisan make:seed UsersTableSeeder
代码语言:javascript复制<?php
use IlluminateDatabaseSeeder;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(AppUser::class,5)->create();
}
}
Post 数据填充
代码语言:javascript复制<?php
use IlluminateDatabaseSeeder;
class PostSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(AppPost::class,50)->create();
}
}
注册数据填充 database/seeds/DatabaseSeeder.php
<?php
use IlluminateDatabaseSeeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call(UsersTableSeeder::class);
$this->call(PostSeeder::class);
}
}
运行迁移文件,进行数据填充
代码语言:javascript复制php artisan db:seed
ok,以上准备工作做完,(其实你大可不必这样,你可以任意创建 User、Post 数据表)我们正式开始今天的话题。
自定义键
首先我们来说一下自定义键是个什么东西,你可能知道,我们如果要查找一个数据,比如,我们要查询 Posts 文章表里的第一条数据。我们的以前的 URL 可能是如下这样:
代码语言:javascript复制http://laravel7.test/posts/posts/1
我们是通过主键 ID 来进行查找的。这种方法 看起来没什么问题,但是我们网站有多少数据用户是可以轻而易举地猜到。
当然我们在以前的版本可以更改这个,我们需要在 模型中重写一个方法 getRouteKeyName
接下来我们看下 Laravel 7 以前是怎么实现的
首先。定义一个路由
代码语言:javascript复制Route::get('posts/{post}', function (AppPost $post) {
dd($post);
});
接下来,我们重写 Post 模型文件 getRouteKeyName
方法。
public function getRouteKeyName()
{
return 'slug';
}
接下来我们就可以使用 slug 来进行查询了 比如下面的 URL
代码语言:javascript复制http://laravel7.test/posts/amet-laudantium-reprehenderit-ullam-repudiandae
Laravel 7 的版本,实现以上自定义键,就更加方便了 只需要在 路由上添加一个动态参数即可。
代码语言:javascript复制Route::get('posts/{post:slug}', function (AppPost $post) {
dd($post);
});
作用域(访问限制)
怎么理解呢?举一个应用场景,我们要限定查找用户,然后在当前用户下查找他发表的文章某一篇文章。
我们代码演示一下
代码语言:javascript复制Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
首先 我们看下 数据库文章表的数据
假如我们查找文章 id 为 1,同时 他的 user_id 是 2, 那么访问的路由就是
代码语言:javascript复制http://laravel7.test/api/users/2/posts/1
那么我们在查找 id 为 2 的数据,可以看到 他的 user_id 并不是 2 了,理论上我们不应该查到才是。
代码语言:javascript复制http://laravel7.test/api/users/2/posts/2
然而实际情况确 并非如此。数据也是返回来了。
文档上就是这样呀?就是改变路由文件而已,照着做了,发现并不可以。
其实如果我们要实现如上的模式,我们还得需要设置模型的绑定关系
Post 模型
代码语言:javascript复制<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
User 模型
代码语言:javascript复制public function posts()
{
return $this->hasMany(Post::class);
}
OK,再试着访问下,纳尼,为什么还是可以访问到???
最终看了半天文档 我发现他给的路由后面有一个 动态参数 slug,加上试试。
代码语言:javascript复制Route::get('api/users/{user}/posts/{post:slug}', function (AppUser $user, AppPost $post) {
return $post;
});
那么 路由就得换成如下的方式:
代码语言:javascript复制http://laravel7.test/api/users/2/posts/et-saepe-enim-minus-et
这下终于可以了,终于实现我们想要的效果了。但是 难道非得是 slug 吗?我换成 id 不行吗?
代码语言:javascript复制Route::get('api/users/{user}/posts/{post:id}', function (AppUser $user, AppPost $post) {
return $post;
});
这样也是可以的。
好了,以上就是 Laravel 7 路由的新特性,外加我趟过的坑,希望对你有帮助。
版权许可
本作品采用 知识共享署名 4.0 国际许可协议 进行许可。 转载无需与我联系,但须注明出处,注明文章来源 Laravel 7 新特性-路由的趟坑之路(自定义键名以及作用域)
联系我