如何将多个表单验证请求链接在一起?

时间:2017-07-19 17:37:18

标签: php laravel validation

在我正在进行的Laravel项目中,我想创建一个API。在该API中,每个请求都将需要某些JSON密钥。例如。一个令牌或其他始终需要的字段。我熟悉Laravel的表单请求功能,它允许您使用包含验证逻辑数组的rules方法轻松创建一个类。但是,我想知道是否有一种方法可以创建一个Request类来处理"始终需要"字段然后在另一个包含该端点的特定字段验证的请求类上进行操作。

E.g。

// MasterRequest.php
public function rules() {
    return [
        'api_key' => 'required|exists:users,api_key',
    ];
}

// ProductRequest.php
public function rules() {
    return [
        'product_id' => 'required|integer',
    ];
}

然后某种方式总是在每条api路由上调用MasterRequest验证,然后为每条路由的独特需求指定请求验证的类型?

这是可行的,甚至是正确的方法吗?

2 个答案:

答案 0 :(得分:2)

这很容易设置,使用PHP的OOP属性。

最简单的方法(也很明显):

让自己成为“总是必需字段的主类”,你也可以将它声明为抽象类。

档案 AlwaysRequired.php

abstract class AlwaysRequired extends FormRequest 
{
    public function rules() {
        return [
            'api_key' => 'required|exists:users,api_key',
        ];
    }
}

ProductRequest.php

class ProductRequest extends AlwaysRequired 
{
    public function rules() {
        return array_merge(parent::rules(), 
                          ['product_id' => 'required|integer']);
    }
}

php.net

上的数组合并

物业方式:

让自己成为大师班级,在其中您将使用“始终需要”规则声明属性,然后在子类中仅使用array_merge(array,...)(就像上面的示例一样)。

“最难”和最令人困惑的方式,但全自动:

您可以利用魔术函数和PHP语言的method/property visibility

再次让自己成为一个大师班,在其中你将protected property拥有__call() magic method的规则数组和实现。

  

注意:您可以在PHP $php -a的交互式shell中测试下面的代码并复制粘贴代码。

abstract class A { // Master class
    protected $rules = ['abc' => 'required'];

    function __call($name, $arg) {
        if(method_exists($this, 'rules')){
            return array_merge($this->rules, $this->rules());
        } else {
            //or handle any other method here...
            die(var_dump($name, $arg));
        }
    }
}

class B extends A { //Generic class just like ProductRequest...
    protected function rules() { // function must be declared as protected! So its invisible for outside world.
        return ['def' => 'required'];
    }
}

$b = new B();
var_dump($b->rules());

它是如何工作的?

Laravel幕后尝试在您指定的请求类(在您的情况下为 ProductRequest )上运行rules()方法,将其声明为受保护表示它不能从其自身或另一个子节点调用,这意味着调用__call()方法而不是在抽象父类中声明。 __call()方法只是确定调用者是否想要调用不存在的(因为设置了受保护的可见性)方法rules(),如果是这样,它会合并孩子的rules()结果为$rules并返回。

检查正确的API密钥应在Middleware处理。

答案 1 :(得分:0)

可以手动一一执行Request类:

function convertUTCDateToLocalDate(date) {
  var newDate = new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);

  var offset = date.getTimezoneOffset() / 60;
  var hours = date.getHours();

  newDate.setHours(hours - offset);

  return newDate;
}