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\RouterapiResource 方法,内容如下

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\RouterapiResource 方法。那么如何在 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 即可。在它的基础上,再添加 enableexport 两个方法实现就可以,如下

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 实现自定义资源路由的更多相关文章

  1. laravel中resource资源路由方法

    新增的 resource 方法将遵从 RESTful 架构为用户资源生成路由.该方法接收两个参数,第一个参数为资源名称,第二个参数为控制器名称. Route::resource('users', 'U ...

  2. laravel Route::resource() 资源路由

    格式: Route::resource('/order', 'OrderController', ['as' => 'admin']); 框架自动创建路由及其对应控制器中的方法: 请求方式 路由 ...

  3. Laravel 5.2 二、HTTP路由、创建控制器 与 资源路由

    一.HTTP路由 所有路由都定义在 App\Providers\RouteServiceProvider 类载入的 app/Http/routes.php文件中. 1. 基本路由 简单的 Larave ...

  4. laravel路由与控制器(资源路由restful)

    目前我们大致了解了laravel下,在开始一个Http程序需要先定义路由.之前的例子中,我们的业务逻辑都是在路由里实现,这对于简单的网站或web应用没什么问题,当我们需要扩大规模,程序变得复杂,分层的 ...

  5. laravel资源路由详解

    大概挑两条解释. 我定义了个资源路由Route::resource('article', 'ArticleController');. 当我访问地址ArticleController的http://y ...

  6. laravel控制器之资源控制器

    资源控制器 Laravel 的资源控制器可以让我们很便捷地构建基于资源的 RESTful 控制器,例如,你可能想要在应用中创建一个控制器,用于处理关于文章存储的 HTTP 请求,使用 Artisan ...

  7. laravel基础课程---3、路由(Laravel中的常见路由有哪几种)

    laravel基础课程---3.路由(Laravel中的常见路由有哪几种) 一.总结 一句话总结: 6种:post,get,put,patch,delete,options Route::get($u ...

  8. 在VC项目中使用自定义资源

    这是我看到的比较实用性的技巧,分享给大家 一.前言 在VC环境中除了我们所常用的Dialog.Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自 ...

  9. Laravel教程 二:路由,视图,控制器工作流程

    Laravel教程 二:路由,视图,控制器工作流程 此文章为原创文章,未经同意,禁止转载. View Controller 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就 ...

  10. Laravel框架初学一路由(基本路由)

    基本路由 Laravel最基本的路由:接收一个URI和Closure闭包函数 ,提供了定义路由的一种非常简单且富有表达力的方式 Route::get("foo", function ...

随机推荐

  1. Go 语言中 For 循环:语法、使用方法和实例教程

    for循环用于多次执行特定的代码块,每次都可以使用不同的值.每次循环执行都称为一次迭代.for循环可以包含最多三个语句: 语法 for 语句1; 语句2; 语句3 { // 每次迭代要执行的代码 } ...

  2. 掌上新闻随心播控,HarmonyOS SDK助力新浪新闻打造精致易用的资讯服务新体验

    原生智能是HarmonyOS NEXT的核心亮点之一,依托HarmonyOS SDK丰富全面的开放能力,开发者只需通过几行代码,即可快速实现AI功能.新浪新闻作为鸿蒙原生应用开发的先行者之一,从有声资 ...

  3. Health Kit申请验证有问题?解决方案全解析

    在接入Health Kit的过程中,应用上线前需要完成申请验证环节,获得正式的运动健康权限. 我们贴心整理了申请验证被驳回的高频问题,您可以在申请前阅读以下内容,避免在您的申请材料中出现下述问题影响审 ...

  4. HMS Core上新啦!

    HMS Core上新啦!分析服务营销分析报告全新上线:运动健康服务支持目标场景事件订阅:音频编辑服务提供专业的三维声音频编辑与渲染能力,更多HMS Core能力可点击网页链接了解. 了解更多详情> ...

  5. 元启发式算法库 MEALPY 初体验-遗传算法为例

    简介 官网: MealPY官网 开源许可: (GPL) V3 MEALPY简介 官网简介翻译 MEALPY (MEta-heuristic ALgorithms in PYthon) 是一个提供最新自 ...

  6. 4天带你上手HarmonyOS ArkUI开发——《HarmonyOS ArkUI入门训练营之健康生活实战》

     <HarmonyOS ArkUI入门训练营之健康饮食应用>是面向入门开发者打造的实战课程系列.特邀华为终端BG高级开发工程师作为本次训练营讲师,以健康饮食为例,开展技术教学及实战案例分享 ...

  7. HarmonyOS助力构建“食用菌智慧农场”

     原文:https://mp.weixin.qq.com/s/qK4aRY5UKc3GvpLxhwpqww,点击链接查看更多技术内容.   [开发者说]栏目是为HarmonyOS开发者提供的展示和分享 ...

  8. TypeScript 中泛型的理解?应用场景?

    一.是什么 泛型程序设计(generic programming)是程序设计语言的一种风格或范式 泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型 ...

  9. 力扣599(java&python)- 两个列表的最小索引总和(简单)

    题目: 假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示. 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅. 如果答案不止一 ...

  10. 力扣172(java)-阶乘后的零(中等)

    题目: 给定一个整数 n ,返回 n! 结果中尾随零的数量. 提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 示例 1: 输入:n = 3输出:0解释: ...