将请求转换为自定义验证请求

Transform Request to custom validation request

是否可以将 Illuminate\Http\Request 转换为您使用 php artisan make:request MyRequest 发出的自定义验证请求?

我希望在以后的方法中进行验证,这样我就可以:

protected function register(Request $request)
{
   ...
   $this->userRepository->signup($request)
   ...
}

用户资料库:

public function signup(MyRequest $request)
{
    ...
}

这可能吗?我现在收到一个错误,因为需要一个 class。唯一想到的就是做一个接口,但是不知道能不能实现。

错误我得到

Type error: Argument 1 passed to UserRepository::signup() must be an instance of App\Http\Requests\MyRequest, instance of Illuminate\Http\Request given

是的,这没有问题,您应该创建:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class MyRequest extends FormRequest
{
   public function rules() {
       // here you put rules
   }
}

在你的控制器中:

public function signup(\App\Http\Requests\MyRequest $request)
{
    ...
}

请注意,您还应该调整请求中的 authorize 方法 class(根据用户访问权限调整为 return true 或 false)

编辑

更新后 - 你应该在控制器和存储库中键入提示你的自定义 class - 这取决于你 - 我经常使用通用 Illuminate\Http\Request,所以你应该这样做:

在控制器中:

public function controllerMethod(\App\Http\Requests\MyRequest $request)

存储库中:

public function signup(\App\Http\Requests\MyRequest $request)

public function signup(\Illuminate\Http\Request $request)

总而言之,您应该在控制器中使用表单请求 classes - 这是进行验证的地方,稍后您可以使用相同的 class 或通用的 \Illuminate\Http\Request - 我个人经常在存储库或服务中使用 \Illuminate\Http\Request 因为他们通常不关心放入 MyRequest class 的其他东西 - 他们只想从请求中获取数据 class 就是这样。

我发现即使使用我的自定义 class 扩展 Request 也无法做我想做的事,因为自然而然地,一种方法在获取时需要一个 class 的实例另一个。

也许可以提取一个接口并包装和绑定它,但在我看来这是一个快速修复。

我的看法是,我的概念从一开始就是错误的,更多的是架构问题,所以我将我的应用程序转换为不同的方法,并设法首先避免此类问题。

嗯,您可以将任何请求转换为任何其他请求,只要它扩展自 Illuminate\Http\Request

Laravel 基本上有两种方法可以将一个请求转换为另一个请求。这里的问题是,当 MyRequest 作为参数传递时,它永远不会获得验证对象或自动触发验证,作为注入的一部分。它也可能会遗漏消息包和错误处理程序,但是您无法通过初始化请求来修复任何问题,就像 Laravel 在注入它时所做的那样。

因此,您仍然必须触发 FormRequest(如果它扩展了 FromRequest 而不是 Request)通常在启动特征时执行的所有序列,但是,这仍然是完全可能的,并且需要一些额外的工作,您可以将任何请求转换为任何其他请求。

例如;我正在使用此设置仅调用一个路由 profile/{section}/save 来保存我的配置文件设置。根据 $section 的值,我将给定的 $Request 转换为我对该特定 $section.

的任何自定义表单请求

use App\Http\Requests\MyRequest;
use Illuminate\Http\Request;

...

public function someControllerMethod(Request $Request) {
   $MyRequest = MyRequest::createFrom($Request);
   // .. or
   $MyRequest = MyRequest::createFromBase($Request);
}

...

因此,为了让人们开始使用 FormRequest 作为示例,基本上就是这样。

不是从默认 Illuminate\Foundation\Http\FormRequest 扩展所有自定义请求,而是使用从 FormRequest 扩展的基础 class 并添加自定义方法来转换和启动请求,就像它作为参数传递。

namespace App\Http\Requests;

use Illuminate\Routing\Redirector;
use Illuminate\Foundation\Http\FormRequest;

class BaseFormRequest extends FormRequest {
   public function convertRequest(string $request_class) : BaseFormRequest {
      $Request = $request_class::createFrom($this);

      $app = app();
      $Request
        ->setContainer($app)
        ->setRedirector($app->make(Redirector::class));

      $Request->prepareForValidation();
      $Request->getValidatorInstance();

      return $Request;
   }

    public function authorize() {
        return true;
    }

    public function rules() {
        return [];
    }
}

让您的所有自定义 FormRequest 扩展您的 BaseFormRequest

namespace App\Http\Requests;

class MyRequest extends BaseFormRequest {
  ...
}

现在任何你想要 convert 请求的地方,在你的控制器方法中使用基础 class 并使用 convertRequest 将其转换为你希望的自定义​​请求 class转换。

public function someControllerMethod(BaseFormRequest $Request) {
  $MyRequest = $Request->convertRequest(MyRequest::class);
}