【问题标题】:How to pass parameters in Laravel Rule?如何在 Laravel Rule 中传递参数?
【发布时间】:2018-10-14 21:17:18
【问题描述】:

我想将此代码移至 App\Rule:

//Currently in class AppServiceProvider extends ServiceProvider

Validator::extend('empty_if', function ($attribute, $value, $parameters, $validator) {
   return ($value != '' && request($parameters[0]) != '') ? false : true;
});

所以应该是这样的:

//in: App\Rules\EmptyIf

public function passes($attribute, $value, $parameters)
{
   return ($value != '' && request($parameters[0]) != '') ? false : true;
}

但我的问题是,我无法传递 $parameters

Validator::extend('empty_if', 'App\Rules\EmptyIf@passes');

你将如何将参数传递给 Laravel Rule?

【问题讨论】:

  • 我不确定你想达到什么目标,你能提供更多细节吗?
  • @Jonathon 对不起,我编辑了我的帖子,现在可能更清楚了。如果不告诉我,请告诉我

标签: laravel


【解决方案1】:

这是一种更简单且更新的方法来完成此操作,无需扩展验证器。您可以在 Rule 的构造函数中访问传递的参数,因此只需设置一个全局范围的变量,现在您可以在 pass() 方法中引用它。您甚至可以使用相同的方法在验证器消息中获取值。

验证调用:

case 'measurement':
 $request->validate([
   'updates.*.value' => [
   new Measurement('foo-bar'),
   ],
 ]);
 break;

规则:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Measurement implements Rule
{
/**
 * Create a new rule instance.
 *
 * @param $param
 */
public function __construct($param)
{
    $this->type = $param;
}

public $type;
/**
 * Determine if the validation rule passes.
 *
 * @param string $attribute
 * @param mixed $value
 * @param array $parameters
 * @return bool
 */
public function passes($attribute, $value)
{
    dd($this->type, 'params');
    return;
}

【讨论】:

    【解决方案2】:

    如果我正确理解您的需求,则无需扩展验证器。

    你似乎有课:

    class EmptyIf extends Rule {
          public function passes($attribute, $value, $parameters) { }
    }
    

    那么你可以把它当作:

    $this->validate($data, [ "entry" => [ new EmptyIf() ] ]);
    

    您可以同时使用:

    Validator::extend('empty_if', function ($attribute, $value, $parameters) {
        return (new EmptyIf())->passes($atribute, $value, $parameters);
     });
    

    【讨论】:

    • 所以我的事情是我想在规则中正常使用它,就像这样:有时|nullable|empty_if:about_image|max:200|url'。所以我需要扩展验证,但是我无法让变量工作$parameters,因为它只传递给参数($attribute,$value)
    • 您做出了选择。要么扩展 Rule 并将其用作规则数组中的对象,要么扩展验证器并将其用作字符串。您可能可以通过在回调中执行新实例来组合它们,但 Classname@FunctionName 并不是真正有效的定义方式
    • 可惜了。有时我看了 laracast 的一个视频,他做了一件事:Validator::extend('spamfree', 'App\Rules\SpamFree@passes');
    • 这个很好用,但是现在我需要获取empty_if:{parameter[0]}的参数,但是无法获取:(
    • 使用类作为验证规则时,似乎不支持任何参数。如果您使用验证器扩展方法,它似乎工作得很好,即使这意味着您需要创建该类的新实例。您可能会在 github 中提出功能请求
    【解决方案3】:

    使用带有必需$parameters 的规则类时,您会收到错误:

    PHP Fatal error:
    Declaration of App\Rules\AgeAt::passes($attribute, $value, $parameters)
    must be compatible with Illuminate\Contracts\Validation\Rule::passes($attribute, $value)
    

    您可以简单地将$parameters 设为可选,您将自动获得在 Laravel 5.5+ 中传递的参数:

    public function passes($attribute, $value, $parameters = [])
    {
        //do something here
    }
    

    【讨论】:

    • 不确定自 Laravel 5.5 以来这是否发生了变化,但它不会自动将 $parameters 传递给此函数。 $parameters 为空。
    【解决方案4】:

    您可以在Rule中使用constructor传递参数

    public function __construct($params)
    {
        $this->params = $params;
    }
    

    然后在passes方法中访问参数

    public function passes($attribute, $value)
    {
      //access params with $this->params
    }
    

    【讨论】:

    • 另一个最佳、正确且有效的答案!
    【解决方案5】:

    您可以通过将参数传递给Rule 的构造函数来做到这一点:

    <?php
    
    namespace App\Rules;
    
    use Illuminate\Contracts\Validation\Rule;
    use Illuminate\Http\Request;
    
    class EmptyIf implements Rule
    {
        public $otherParameter;
    
        public function passes($attribute, $value)
        {
            if (Request::get($this->otherParameter) != '') {
                return ($value == '');
            }
    
            return true;
        }
    
        public function message()
        {
            return 'The :attribute cannot be empty if ' . $this->otherParameter . ' is set';
        }
    }
    

    在服务提供者中:

    <?php
    
    namespace App\Providers;
    
    use App\Rules\EmptyIf;
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap services.
         */
        public function boot(): void
        {
            Validator::extend('empty_if', function($attribute, $value, $parameters, $validator) {
                $rule = new EmptyIf($parameters[0]);
    
                return $rule->passes();
            });
        }
    }
    

    所以现在你可以在验证器中使用字符串形式了:

    'sometimes|nullable|empty_if:about_image|max:200|url'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多