mmedia / classcontroller
一个可以将标准PHP类转换为具有自动验证的控制器方法的控制器。
Requires
- php: ^7.4|^8.0
- illuminate/support: ^8.0
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2024-09-14 17:26:50 UTC
README
ClassController 扩展了基本的 Controller,允许您直接使用定义的 PHP 类方法作为控制器方法。
安装
您可以通过 composer 安装此包
composer require mmedia/classcontroller
使用方法
查看此示例使用的 Test::class
。
use MMedia\ClassController\Http\Controllers\ClassController; class TestClassController extends ClassController { protected $inheritedClass = 'MMedia\ClassController\Examples\Test'; //Done. All methods from the class Test are inherited and wrapped in Laravel validation automatically }
当您扩展 ClassController
并将新控制器命名为 {inheritedClass}ClassController
时,所有 {inheritedClass}
的方法都会继承并包裹在 Laravel 验证规则和响应中。如果您需要一个命名空间类,可以使用 inheritedClass
属性来指定具有其命名空间的类。
在您的路由中,现在可以直接调用继承类的所有方法,例如,在当前情况下直接调用 Test::class
。
// We're just using the methods in the inherited class methods directly Route::get('/noParams', [TestClassController::class, 'noParams']); // === \Test::noParams() Route::get('/mixedParam/{param}', [TestClassController::class, 'mixedParam']); // === \Test::mixedParam($param) + auto validation!
以下是扩展默认 Controller 时的等效示例
在 `ClassController` 中,所有这些代码都由您自动处理!<?php namespace App\Http\Controllers\Api\Test; use Illuminate\Http\Request; class TestController extends Controller { public function noParams(Request $request) { $testClass = new Test(); try { $methodResult = $testClass->noParams(); if ($request->wantsJson()) { return response()->json($methodResult, 200); } return back()->with('success', $methodResult); } catch (\Exception $e) { return abort(400, $e->getMessage()); } } public function mixedParam(Request $request) { $validatedData = $request->validate([ 'param' => ['required', 'integer'], ]); $testClass = new Test(); try { $methodResult = $testClass->mixedParam($validatedData['param']); if ($request->wantsJson()) { return response()->json($methodResult, 200); } return back()->with('success', $methodResult); } catch (\Exception $e) { return abort(400, $e->getMessage()); } } }
定义传递给继承类构造函数的参数
有时类需要在构造函数中一些参数。要定义这些参数,您的控制器应实现 classParameters
方法,并按正确顺序返回所需的参数作为可迭代的对象。
protected function classParameters(): iterable { return [$param1, $param2]; }
在实例化后的类上进一步设置
如果您需要在调用方法之前但在设置和实例化之后对类进行更多操作,您可以实现 postClassSetup
方法,其中您可以通过 $this->class()
访问类的实例。此方法不应返回任何内容。
protected function postClassSetup(): void { // Your code here. You have access to $this->class(). }
覆盖特定方法
如果您需要覆盖特定方法的行为,您只需在控制器中按要覆盖的方法名称定义它即可。使用原始示例 Test::class
public function mixedParam(Request $request) { // You can write your own $request->validate(), or use the one from ClassController which validates that the data passed to the original class method is correct $validatedData = $this->getValidatedData($this->class(), 'mixedParam'); // Call the original method if you want, or override it completely return $this->class()->mixedParam($validatedData['param']); }
请注意,虽然您可以编写自己的验证逻辑,但在这里我们选择使用 ValidatesClassMethods
trait 提供的现有方法 getValidatedData()
- 此方法接受类名和方法名作为参数,然后验证所有必需的方法参数。
使用 Laravel Artisan 创建 ClassController
首先,确保使用以下命令发布存根
php artisan vendor:publish --tag=classcontroller-stubs
然后,您可以使用 Artisan 命令在需要时创建 ClassControllers。指定 ---type=class
选项,然后跟随着您要继承的类名,以创建新的 ClassController
php artisan make:controller --type=class TestClassController
详细说明
响应
根据您的头部信息,ClassController 将以不同的方式响应。如果您传递 Accept:application/json
头部信息,响应将以 JSON 格式呈现。否则,您将被重定向回上一个页面,如果有抛出的验证错误,则会显示验证错误;如果没有错误,则显示成功的操作结果。
验证
验证规则是通过类方法参数构建的。例如,一个函数test($param1, $param2)
将构建一个验证器,该验证器要求在request
中传递param1
和param2
。
如果参数有默认值,例如test($param1 = "defaultValue")
,则param1
的验证规则将是nullable
。
如果参数是类型化的,例如test(int $param1)
,则param1
的验证规则将是required
和integer
。
如果参数是可变参数,例如test(...$param1)
,则param1
的验证规则将是required
和array
。
如果参数是可变参数并且是类型化的,例如test(int ...$param1)
,则param1
的验证规则将是required
和array
,并且每个元素也将有一个类型为integer
的验证规则。
异常
验证异常
验证异常将由Laravel验证器原生处理,并以状态码422
返回errors
键中的错误。例如,一个验证异常可能返回如下:
{ "errors": { "param": [ "Param is required.", "Param must be an integer." ] } }
记住,您必须传递accept
头来获取JSON数据。
方法异常
如果调用方法抛出异常,它将被ClassController捕获。如果您已指定响应中接受JSON,则消息将以JSON格式返回,键值为{"message": "错误消息"}
,状态码为400
。否则,将显示Laravel 400页面。
ClassController异常
ClassController本身可能抛出异常,尤其是如果它没有正确设置。例如:如果无法确定继承类,您将收到一个带有明确消息和状态码为500
的原始PHP错误。
所有方法
classParameters(): iterable
传递给继承类构造函数的参数。 查看:定义传递给类的参数。
postClassSetup(): void
在类实例化后运行的函数。 查看:实例化后进一步设置类。
getValidatedData($className, $methodName): array
该方法接收一个方法名和一个类名,遍历方法参数,生成Laravel验证实例,并使用Laravel规则进行验证。返回有效数据数组,或在存在验证错误时抛出ValidationException
。 查看:验证。
class(): object
获取继承类的实例。实际的类实例,已经实例化。
所有属性
inheritedClass
受保护的字符串('MyClass')或类(MyClass::class
)。这将是方法继承的类。
如果您没有定义此属性,并且您的控制器遵循{inheritedClass}ClassController extends ClassController
的命名标准,则inheritedClass
将来自您控制器的名称。
ValidatesClassMethods
特性
如果您想使用验证器方法但不想扩展您的控制器以使用ClassController
类(或想在控制器之外使用验证逻辑),则可以在您的代码中使用ValidatesClassMethods
特性。
use MMedia\ClassController\ValidatesClassMethods; class myClass { use ValidatesClassMethods; /** * Example method showing how to use the `getValidatedData` method. * * @param string $param1 * @param int|null $param2 * @throws ValidationException * @return string */ public function test(string $param1, ?int $param2) { // Note: in the real world, it makes little sense to get validated data from within the same method as the method that is being called - PHP would have already thrown an error if the params were not valid types. $validatedData = $this->getValidatedData(get_class($this), __FUNCTION__); // Your code here. $validatedData['param1'] is a valid string and $validatedData['param2'] is a valid integer or null. return $validatedData['param1'] . $validatedData['param2']; } }
限制
- 无类型的方法参数不会生成特定的类型验证规则 - 查看:验证
- 类型为数组的方法参数不会验证每个数组元素
- 未指定参数而是使用
func_get_args()
的方法不会生成任何验证规则 - 授权未实现 - 然而,您可以在路由级别授权请求
包开发
运行
您可以使用包含的VSCode devcontainer在PHP容器中开发。
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志
贡献
有关详细信息,请参阅贡献指南
安全性
如果您发现任何安全相关的问题,请通过电子邮件contact@mmediagroup.fr联系,而不是使用问题跟踪器。
鸣谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件