【问题标题】:How to call controller internally which is receiving Custom Form Request validation parameter如何在内部调用接收自定义表单请求验证参数的控制器
【发布时间】:2019-04-05 01:54:41
【问题描述】:

我从两个地方调用控制器方法store。首先直接从表单提交,意味着一旦我提交了来自store的方法就会被调用。

第二种方法是从laravel的其他方法中调用store方法。这是store方法代码。

public function store(MedicalAidRequest $request)
{
    //
    if(Auth::check()){
        $medicalAidRequest = session('medical_aid_request', $request->all());
        $medicalAidRequest['user_id'] = Auth::id();
        return $this->aidRepository->add($medicalAidRequest);
    }else{
        session(['medical_aid_request' => $request->all()]);
        return redirect('login')->with('from', 'aid_request');
    }
}

我使用这段代码是因为我想达到以下要求。

  • 如果用户已登录,请提交医疗救助。
  • 如果用户未登录,则将请求数据存储在会话中并请求登录,一旦用户登录,则再次调用store方法从会话中检索表单数据并保存到数据库。

但是当我在记录后内部调用store 方法时,由于store 参数中的MedicalAidRequest 在调用store 方法之前验证来自表单请求的数据,验证失败。那么我该如何实现呢?

【问题讨论】:

    标签: laravel validation


    【解决方案1】:

    首先:

    在内部,您可以使用有效数据创建请求,然后在调用时传递给store 方法。

    您可以如下创建请求:

    $request = new <Namespace>\MedicalAidRequest();

    然后您可以使用 replace 方法手动添加输入,如下所示:

    $request->replace(['key' => 'value']);
    $controller = new YourController();
    $controller->store($request);
    

    其次

    您可以在控制器内部验证请求,而不是在表单请求中验证。如果这样做,您可以在 store 方法中传递一个标志,例如 $isInternal 如果内部是 true 则不要运行验证。方法如下:

    public function store($isInternal = false)
    {
      if(!$isInternal){
        $this->validate(request(), $this->rules());
      }
      //Rest of the code remain same
    }
    
    private function rules():array
    {
      //return your rules array here as in the MedicalAidRequest
    }
    

    【讨论】:

    • 如何调用请求?正如您在第一种技术中添加的那样。
    • $this->store($request);我没有从同一个控制器调用 store 方法。我从控制器外部调用store 方法。
    • 然后您可以创建该控制器的实例。喜欢:$controller = new YourController();$controller->store($request);。答案已更新。
    • 你真的认为它是认证方式吗?创建看起来很尴尬的控制器实例。
    • 这是一个很好的问题。这只是您想要实现的目标的解决方案。理想情况下,不应从另一个控制器调用一个控制器的方法。这不是关于身份验证(我的意思是真实的方式),而是关于代码设计。您可以将公共代码放在存储库或服务中。然后从控制器调用它。这只是您告诉您想要做的事情的解决方案。如何在不创建实例的情况下从另一个控制器调用控制器方法?
    【解决方案2】:

    我在将内部调用转发到另一个控制器时遇到了同样的问题。

    要解决这个问题,您必须创建一个新的 request 对象,其中包含所有需要的参数,然后让 app 内核 处理它。 通过这种方式,Laravel 会像在浏览器中一样处理精心制作的请求。

    如上所述,创建请求并在应用实例上调用handle方法:

    $request = Request::create($url, $action, $params, $cookies, $files, $headers);
    
    $response = app()->handle($request);
    
    // If needed you can use the response of the internal call
    // if ($response->getStatusCode() == 404) {
    //     abort(404);
    // }
    

    如果您在多个地方需要该功能,您可以决定将其提取到它自己的trait(最快的方式);或将逻辑移动到您将在应用容器中绑定的自己的中。

    后一种方式允许仅在需要时通过 Laravel 的 typehinting injection 从方法的签名中解析依赖项,或通过app() 实例手动处理。

    如果您需要关于类提取/绑定的进一步说明,请告诉我,我会详细说明我的答案。

    【讨论】:

      猜你喜欢
      • 2016-05-22
      • 2016-11-12
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多