在我正在进行的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验证,然后为每条路由的独特需求指定请求验证的类型?
这是可行的,甚至是正确的方法吗?
答案 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']);
}
}
上的数组合并
让自己成为大师班级,在其中您将使用“始终需要”规则声明属性,然后在子类中仅使用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;
}