【问题标题】:Form request validation in Laravel: required depending on the method (POST, PUT or DELETE)Laravel 中的表单请求验证:需要取决于方法(POST、PUT 或 DELETE)
【发布时间】:2021-03-05 00:31:43
【问题描述】:

我在 Laravel 中使用表单请求进行验证。我注意到一种一直出现的模式,但我在 SE 上找不到解决方案(或者至少谷歌搜索对我没有帮助)。

假设我们正在创建一个 API,并且我们正在使用 Laravel 的 apiResource 来创建常用的 CRUD 方法:storeupdatedelete

显然,当我们存储新记录时,字段 id 不是必需的,但其余字段可能是必需的(并且在大多数情况下是必需的)。但是当我们更新记录时,我们面临相反的情况。 id 为必填项,其他字段不再需要。

是否可以在 Laravel 中通过一个表单请求来处理这种情况?我们可以智能地使用 Laravel 的required_if 来避免代码重复吗?

编辑:它不一定是 Laravel 解决方案。使用 PHP 的解决方案也可以(只要它干净且遵循 SOLID 原则)。

【问题讨论】:

  • 您是否将 id 字段公开为可由用户操作的表单输入?如果 id 是主键,则不建议公开 id 字段以通过表单进行操作。如果您没有通过表单公开 id 字段,那么我猜它甚至不需要任何验证。

标签: php laravel validation


【解决方案1】:

这是我想出的两种可能的解决方案

  1. 使用控制器方法返回正确的验证规则:
    public function rules()
    {
        $method = $this->route()->getActionMethod();

        switch($method){
            case 'store':
                return [
                    \\ validation rules
                ]
            ...
        }
    }
  1. 使用$this->getMethod() 代替$this->route()->getActionMethod() 并通过HTTP 方法进行验证。

您还可以将验证规则存储在一个数组中并对其进行操作以减少代码重复。

我认为这在很大程度上解决了代码重复的问题。

【讨论】:

  • 1) 我已经在其他用户上回复了此问题,但您仍然在某种程度上破坏了 (SOLID)。现在控制器还必须知道要使用哪些规则,如果它在 FormRequest 中,那就是 FormRequest 职责。 2)这也是一个好方法。我会一直坚持重复FormRequests,而不是让一些不太清晰的东西。
【解决方案2】:

检查方法然后根据该方法返回一组规则呢?例如,我有一个具有以下规则的 InvoiceFormRequest。所以我可以将一个表单请求用于两种不同的方法。

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
    if ($this->isMethod('post')) {
        return [
           'template' => 'required',
           'due_by_date'   => 'required',
           'description'   => 'required',
           'charge_items'  => 'required',
        ];
    }

    if ($this->isMethod('put')) {
        return [
            'due_by_date'   => 'required',
            'description'   => 'required',
            'charge_items'  => 'required',
        ];
    }
}

【讨论】:

  • @stressedout 这不是一个糟糕的解决方案,但您仍然只在一个文件中保留规则(破坏 SOLID),但如果您还必须使用 authorize如果那部分,你会再做一次。
【解决方案3】:

我多次遇到这个问题,我理解你的沮丧......

从我的角度和专业经验来看,最好的解决方案是始终为每个案例提供特定的FormRequests:

  • store 有自己的规则
  • update 的其他规则类似但与store 不同
  • 最后一个是delete(肯定比其他规则少,而且没有重复)

我知道你说“没有代码重复”,但就目前而言,这是不可能的(但你不应该像我之前所说的那样重复代码)。

你说“只要它是干净的并且遵循 SOLID 原则”,记住 SOLID,S = Single Responsability,所以如果你想用一个 FormRequest 解决这个问题,你已经打破了 S . 我无法为具有 10 或 15 个输入的FormRequest 成像,这取决于它是storeupdate 还是delete。这将是不干净的,肯定不会遵循 SOLID 原则。

【讨论】:

  • 好吧,我不得不部分同意你的最后一段。但我认为 SOLID 可以解释,因为应该被视为“责任”的定义可能因人而异。至于我,验证模型的传入数据是一项职责,即使它被分解为几个子案例。我想我可能会想出一个解决方案,所以如果我能找到它,我会告诉你(如果你不介意的话)。
  • @stressedout 请与我分享您的最佳解决方案!我很乐意看看它!但是不,SOLID 不开放解释,单一职责就是单一职责,例如,如果您的代码仅在媒体(Facebook、Twitter、Instagram 等)上共享 URL,则您的责任不会是检查您想要和拥有的媒体一个文件和很多 IF,你应该有一个文件和一个使其动态的模式,但不是传说中的20 cases switch(希望你关注我)
  • 好的,谢谢。当我提出解决方案时,我将等待您的反馈。但是如果我碰巧在这里写了一个答案,也请向我解释为什么写 if 或 case-switch 语句是一个坏主意,因为我看不出它们有问题。
  • @stressedout 拥有 if 或 case-switch 语句还不错,但如果最好的方法不同,那可能会很糟糕,正如我之前所说的那样,如果你的代码共享一个媒体中的 URL,作为初学者,你肯定会使用很多 ifswitch,你应该使用 Builder 模式。我不是 100% 擅长模式,这是我必须掌握的东西,但了解基本模式(如 Builder、Mapper 等)很重要。
  • @matiaslauriti 我同意我们在设计项目时需要牢记 SOLID 原则。我也同意您在需要时创建特定请求文件的方法。对我来说,以 UserPostRequest 和 UserPutRequest 为例更有意义。
猜你喜欢
  • 2015-05-17
  • 1970-01-01
  • 2012-01-25
  • 2017-10-23
  • 2019-04-12
  • 1970-01-01
  • 2010-09-26
  • 2018-03-23
相关资源
最近更新 更多