Laravel 实现自定义资源路由
Laravel 如何实现自定义资源路由
最近在开发过程中,发现总有一些路由需要重复定义,比如切换状态,导出,回收站啊之类的。如果使用 Laravel 自带的资源路由方法,还不足以满足重复劳动得过程。所以是否有方法可以自定义项目得资源路由呢?在 Laravel 中,资源路由一般有两种
服务端渲染
Route::resource('xxxxx')
resource
路由包含以下几个方法
- index
- store
- create
- show
- edit
- upate
- destroy
Api 资源路由
Route::apiResource('xxxxx')
而 ApiResource
则是用 Resource
方法生成,仅仅保存了下面几个方法
$only = ['index', 'show', 'store', 'update', 'destroy'];
现在项目一般都采用前后端分离,所以一般都是使用 apiResource
这个方法,这个方法如上所示只提供五个方法,即五个路由。所以如果项目中需要一些特定得每次都加得路由,必须还要自己再添加一条,很不方便。那在 Laravel 中是不是可以自己扩展属于项目独有得 resource
方法呢?答案是当然可以,而且非常简单
如何实现
一般都是在项目中这样定义资源路由的, 通过门面 Route
访问 apiResource
方法进行定义,如下
Route::apiResource('hello', HelloController::class);
实际上通过门面调用的实际是 Illuminate\Routing\Router
的 apiResource
方法,内容如下
public function apiResource($name, $controller, array $options = [])
{
$only = ['index', 'show', 'store', 'update', 'destroy'];
if (isset($options['except'])) {
$only = array_diff($only, (array) $options['except']);
}
// 实际调用的是 resource 方法
return $this->resource($name, $controller, array_merge([
'only' => $only,
], $options));
}
实际上 apiResource
是用 resource
方法包装的,所以再来看看 resource
方法做了啥
public function resource($name, $controller, array $options = [])
{
// 这里是关键的地方
if ($this->container && $this->container->bound(ResourceRegistrar::class)) {
$registrar = $this->container->make(ResourceRegistrar::class);
} else {
$registrar = new ResourceRegistrar($this);
}
// 这一步不用关注
return new PendingResourceRegistration(
$registrar, $name, $controller, $options
);
}
最关键的地方就是 ResourceRegistrar
,这里就叫资源路由注册器
吧。
- 首先查找容器中是否有资源路由注册器的绑定实现,如果有,直接从容器中 make 出来
- 如果容器中没有绑定,则直接使用 new 实例化
那就是说,如果自定义自己的资源路由注册器,然后再绑定 ResourceRegistrar
的实现,就可以实现让框架使用自定义的路由注册器了。
这解决了资源路由注册器的问题,还需要一个方法来调用,从上来得知
Route::apiResource('hello', HelloController::class);
实际上就是 Illuminate\Routing\Router
的 apiResource
方法。那么如何在 Illuminate\Routing\Router
添加自定义方法呢?没错,首先就要想到它支不支持
Macroable
? 显而易见,肯定是支持的,那么依葫芦画瓢,去注册一个吧。找到 AppServiceProvider
,在里面注册即可
添加自定义的资源路由方法
因为是做后台系统项目,这里就将资源路由方法定义为 adminResource
吧
Router::macro('adminResource', function ($name, $controller, array $options = []) {
// 这里添加 enable 和 export
$only = ['index', 'show', 'store', 'update', 'destroy', 'enable', 'export'];
if (isset($options['except'])) {
$only = array_diff($only, (array) $options['except']);
}
return $this->resource($name, $controller, array_merge([
'only' => $only,
], $options));
});
实现一个资源路由注册器
当然并不是自己去实现,而是集成 Illuminate\Routing\ResourceRegistrar
即可。在它的基础上,再添加 enable
和 export
两个方法实现就可以,如下
namespace Defined;
use Illuminate\Routing\ResourceRegistrar as LaravelResourceRegistrar;
use Illuminate\Routing\Route;
class ResourceRegistrar extends LaravelResourceRegistrar
{
protected $resourceDefaults = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy', 'enable', 'export'];
// 添加 enable 方法路由
protected function addResourceEnable($name, $base, $controller, $options): Route
{
$name = $this->getShallowName($name, $options);
$uri = $this->getResourceUri($name).'/enable/{'.$base.'}';
$action = $this->getResourceAction($name, $controller, 'enable', $options);
return $this->router->put($uri, $action);
}
// 添加 export 方法路由
protected function addResourceExport($name, $base, $controller, $options): Route
{
$uri = $this->getResourceUri($name).'/export';
unset($options['missing']);
$action = $this->getResourceAction($name, $controller, 'export', $options);
return $this->router->get($uri, $action);
}
}
实现好了之后,还需要绑定到容器里, 还是找到 AppServiceProvider
,在里面注册即可
// 资源路由注册器
$this->app->bind(ResourceRegistrar::class, \Defined\ResourceRegistrar::class);
完成之后测试一下看看,我本地使用 UserController 测试
Route::adminResource('users', UserController::class);
完成之后呢,使用 php artisan route:list | grep users
查看
GET|HEAD api/users ................... users.index › UserController@index
POST api/users ....................... users.store › UserController@store
# put 请求 符合预期
PUT api/users/enable/{user} ...........users.enable › UserController@enable
# Get 请求 符合预期
GET|HEAD api/users/export ............. users.export › UserController@export
GET|HEAD api/users/{user} ............. users.show › UserController@show
PUT|PATCH api/users/{user} ............users.update › UserController@update
DELETE api/users/{user} ............... users.destroy › UserController@destroy
Laravel 实现自定义资源路由的更多相关文章
- laravel中resource资源路由方法
新增的 resource 方法将遵从 RESTful 架构为用户资源生成路由.该方法接收两个参数,第一个参数为资源名称,第二个参数为控制器名称. Route::resource('users', 'U ...
- laravel Route::resource() 资源路由
格式: Route::resource('/order', 'OrderController', ['as' => 'admin']); 框架自动创建路由及其对应控制器中的方法: 请求方式 路由 ...
- Laravel 5.2 二、HTTP路由、创建控制器 与 资源路由
一.HTTP路由 所有路由都定义在 App\Providers\RouteServiceProvider 类载入的 app/Http/routes.php文件中. 1. 基本路由 简单的 Larave ...
- laravel路由与控制器(资源路由restful)
目前我们大致了解了laravel下,在开始一个Http程序需要先定义路由.之前的例子中,我们的业务逻辑都是在路由里实现,这对于简单的网站或web应用没什么问题,当我们需要扩大规模,程序变得复杂,分层的 ...
- laravel资源路由详解
大概挑两条解释. 我定义了个资源路由Route::resource('article', 'ArticleController');. 当我访问地址ArticleController的http://y ...
- laravel控制器之资源控制器
资源控制器 Laravel 的资源控制器可以让我们很便捷地构建基于资源的 RESTful 控制器,例如,你可能想要在应用中创建一个控制器,用于处理关于文章存储的 HTTP 请求,使用 Artisan ...
- laravel基础课程---3、路由(Laravel中的常见路由有哪几种)
laravel基础课程---3.路由(Laravel中的常见路由有哪几种) 一.总结 一句话总结: 6种:post,get,put,patch,delete,options Route::get($u ...
- 在VC项目中使用自定义资源
这是我看到的比较实用性的技巧,分享给大家 一.前言 在VC环境中除了我们所常用的Dialog.Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自 ...
- Laravel教程 二:路由,视图,控制器工作流程
Laravel教程 二:路由,视图,控制器工作流程 此文章为原创文章,未经同意,禁止转载. View Controller 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就 ...
- Laravel框架初学一路由(基本路由)
基本路由 Laravel最基本的路由:接收一个URI和Closure闭包函数 ,提供了定义路由的一种非常简单且富有表达力的方式 Route::get("foo", function ...
随机推荐
- JDK11的新特性:HTTP API和reactive streams
目录 简介 怎么在java中使用reactive streams POST请求的例子 总结 JDK11的新特性:HTTP API和reactive streams 简介 在JDK11的新特性:新的HT ...
- 为什么 L1 正则化能做特征选择而 L2 正则化不能
假设我们的模型只有一个参数 \(w\),损失函数为 \(L(w)\),加入 L1 和 L2 正则化后的损失函数分别记为 \(J_1(w), J_2(w)\): \[\begin{gathered} J ...
- Matplotlib绘图设置---文字和标签
文字和文字位置 通过plt.text()或ax.text()命令可在图形上添加文字. Signature: ax.text(x, y, s, fontdict=None, withdash=<d ...
- BZOJ 4403序列统计
假设存在一个满足条件的长度为i的不下降序列(显然是一定存在的)那么只需要从中选出i个数即可 (不必在意选出具体数的大小,可以把满足条件的序列写下来,选几个数感受一下). 但是$n \choose m ...
- 实战指南:使用 xUnit.DependencyInjection 在单元测试中实现依赖注入【完整教程】
引言 上一篇我们创建了一个Sample.Api项目和Sample.Repository,并且带大家熟悉了一下Moq的概念,这一章我们来实战一下在xUnit项目使用依赖注入. Xunit.Depende ...
- redis 简单整理——redis 的哈希基本结构和命令[三]
前言 简单介绍一下哈希基本结构和命令. 正文 什么是hash呢? hash也可以叫做字典.关联数组. 哈希类型是键本身又是一个键值对结构: value={{field1,value1},...{fie ...
- PIL.Image, numpy, tensor, cv2 之间的互转,以及在cv2在图片上画各种形状的线
''' PIL.Image, numpy, tensor, cv2 之间的互转 ''' import cv2 import torch from PIL import Image import num ...
- Sarsa模型和Q_learning模型简记
1. Sarsa模型 1.1 Sarsa类代码: class SarsaAgent(object): def __init__(self,state_n,action_n,learning_rate= ...
- vue登录3D效果
实现的效果 登录动态效果很炫酷,话不多说直接上代码: 组件template <template> <div class="entrance"> <di ...
- 《Effective C#》系列之(六)——提高多线程的性能
一.综述 <Effective C#>中提高多线程性能的方法主要有以下几点: 避免锁竞争:锁的使用会导致线程阻塞,从而影响程序的性能.为了避免锁竞争,可以采用无锁编程技术,如CAS(Com ...