mmedia/classcontroller

一个可以将标准PHP类转换为具有自动验证的控制器方法的控制器。

1.2.1 2022-07-14 08:14 UTC

This package is auto-updated.

Last update: 2024-09-14 17:26:50 UTC


README

Latest Version on Packagist Total Downloads Maintained Coverage

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中传递param1param2

如果参数有默认值,例如test($param1 = "defaultValue"),则param1的验证规则将是nullable

如果参数是类型化的,例如test(int $param1),则param1的验证规则将是requiredinteger

如果参数是可变参数,例如test(...$param1),则param1的验证规则将是requiredarray

如果参数是可变参数并且是类型化的,例如test(int ...$param1),则param1的验证规则将是requiredarray,并且每个元素也将有一个类型为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)。有关更多信息,请参阅许可证文件