路由模型绑定
普通方法:
Route::get('/article/{id}', function($id){
$article = \App\User::find($id);
}
修改服务提供者实现绑定:
修改RouteServiceProvider
中的boot
方法,此时每一个参数的id
值都会被对应为一个Article
实例。
public function boot(Router $router)
{
$router->model('article', Article::class);
parent::boot($router);
}
显式绑定:
同样是修改RouteServiceProvider
中的boot
方法,在其中显示指定绑定关系,同时还可以添加异常处理
public function boot(Router $router)
{
$router->bind('article', Article::class, function() {
throw new NotFoundHttpException; //闭包函数用于处理异常
});
parent::boot($router);
}
隐式绑定:
隐式绑定只需在路由定义中的闭包函数或者是控制器的函数中声明参数(该参数应该与路由参数一致)即可
Route::get('/article/{article}', function(\App\Article $article) {
dd ($article)
}
路由 Resource
Route::resource('users', 'UsersController');
该方法一条语句等同于:
Route::get('/users', 'UsersController@index')->name('users.index');
Route::get('/users/{user}', 'UsersController@show')->name('users.show');
Route::get('/users/create', 'UsersController@create')->name('users.create');
Route::post('/users', 'UsersController@store')->name('users.store');
Route::get('/users/{user}/edit', 'UsersController@edit')->name('users.edit');
Route::patch('/users/{user}', 'UsersController@update')->name('users.update');
Route::delete('/users/{user}', 'UsersController@destroy')->name('users.destroy');
API:
资源类:
资源类用于将给定模型转换成为数组,默认存放路径为app/Http/Resourcces
,生成命令如下:
php artisan make:resource ArticleResource
如果需要对生成的数据进行选择性展示,可以对toArray()
进行修改,比如:
return [
'type' => 'article',
'id' => (string)$this->id,
'article' => [
'title' => $this->title,
'content' => $this->content,
],
'category' => new ArticleCategoryResource($this->cate), //利用资源集合获取分类(不止一个)
'urls' => url('api/articles/'.$this->id),
];
资源集合:
资源集合用于转换整个模型集合,创建时需要用--collection
标识或者是在名字中含有collection
以便框架能够区分是否生成为资源集合类
php artisan make:resource CategoryCollection //方法1
php artisan make:resource --collection Category //方法2
资源类和资源集合类的使用场景:
资源类常用於单个数据,但是所有的资源类都提供了collection
方法,可以生成符合资源类要求的资源集合,但是这种方式生成的资源集合不支持添加元信息。在路由或控制器中用以下语句即可调用
return ArticleResource::collection(Article::paginate()); //此处返回分页后的资源集合
如果需要和集合同步返回一些元数据,就需要单独定义一个资源类,定义方法如上所述。定义之后按照需求修改toArray
中的内容,最后的调用方法同资源类一样,但是这种方式不支持数据内容的定制。
return new AllArticleResource(Article::paginate());
两者各有其特点,资源类能定制数据格式,但是不支持元数据的添加;资源集合能支持元数据的添加,但是不支持数据格式定制。这里可以通过在资源集合中调用资源类来同时实现两者功能,只需在资源集合的toArray
函数中调用资源类,如下所示:
return [
'data' => ArticleResource::collection($this->collection), // 调用资源类
'links' => [
'self' => 'link-value'
]
];
数据包装:
默认资源类返回的json
数据包裹在data
字段中,如果不需要则可以在请求的地方(通常是控制器)或AppServiceProvider
的boot
方法中写入:
Resource::withoutWrapping()
添加元数据:
方法1:在return
处进行修改
return [
'data' => parent::toArray($request),
'links' => [
'self' => 'link-value',
],
];
方法2:利用with
函数直接修改顶层元数据
public function with($request)
{
return [
'links' => [
'self' => url('api/articles/'.$this->id),
],
];
}
分页:
需要分页时在请求的地方写成如下形式即可:
return new ArticleResource(Article::paginate()); // 分页,分页时withoutWeapping无效
关联关系(程序层面的外键实现):
关联关系理解的典型的场景如一个作者对应多个文章。实现时先在模型类(此处是Article
)中定义外键的方法,声明外键
public function cate()
{
return $this->hasMany(Category::class, 'id', 'category_id'); //参数1是关联表名,参数2是外键字段名(关联表中的主键),参数3是本表中的对应外键的字段
}
如果需要修改修改关联关系得到的结果,则可以定义个资源类或资源集合类,在其中进行修改
return [
'cate_id' => $this->first()->id, //此处关联获取的是一个列表,所以需要first
'name' => $this->first()->name,
];
在一开始的资源类中调用外键:
[
// ...
'category' => new ArticleCategoryResource($this->cate),
]
两者ArticleCategoryResource
中return
分别对应的如下的解析方式:
'cate_id' => $this->first()->id, //此处关联获取的是一个列表(原本是一对多的场景,此处演示为一对一)
其它
className::class
指代该类完全命名空间的路径N + 1
查询是指数据库中对某个表做1
次查询需要对其它表做N
次查询Laravel dd
函数等同dump()
+die()
,打印出变量并结束脚本运行- 更多(带条件的属性、合并带条件的属性、带条件的关联关系等)请查看
Laravel api
文档