如何在 Laravel 中使用 setter 方法设置验证规则?

Posted

技术标签:

【中文标题】如何在 Laravel 中使用 setter 方法设置验证规则?【英文标题】:How to set the validation rules using a setter method in Laravel? 【发布时间】:2016-01-18 10:01:05 【问题描述】:

我需要使用setter方法在Validator Class中设置$rules数组。

我需要使用 setter 设置定义的 $rules,因为规则存储在数据库中。我需要使用 Eloquent 来查询数据库以确定规则是什么样的。

我扩展了 Validator 类并添加了一个名为 setCustomRules() 的方法。我在这个方法中注入了一个类,这将允许我使用 Eloquent 读取数据库以确定规则。

但是,当 Laravel 尝试验证时,我将如何强制触发 setCustomRules() 方法?必须先执行此方法,以确保在进行验证之前设置规则。

这就是我所做的

<?php namespace Vend\Surveys\Validator\SurveyAnswers;

use Cartalyst\Support\Validator;

use Vend\Surveys\Repositories\SurveyAnswers\SurveyAnswerDefinedRepository;

class SurveyAnswerDefinedValidator extends Validator implements SurveyAnswerDefinedValidatorInterface 

    /**
     * @inheritDoc
     */
    protected $rules;

    /**
     * @inheritDoc
     */
    public function onUpdate()
    

    


    public function setCustomRules(SurveyAnswerDefinedRepository $rules)
    

        foreach($rules as $rule)
            $this->rules[$rule->name] = $rule->spec;
        

        //this should display the rules that will be used to validate the form
        dd($this->rules);
    



已编辑 根据 The Alpha 的回答,我创建了一个事件处理程序,可以让我创建规则。但不知道如何告诉 Laravel 现在进行验证。

这是我的 EventHandler 类

<?php namespace vend\Surveys\Handlers\SurveyAnswers;

use Illuminate\Events\Dispatcher;
use vend\Surveys\Models\SurveyAnswerDefined;
use Cartalyst\Support\Handlers\EventHandler as BaseEventHandler;

use vend\Surveys\Repositories\SurveyQuestions\SurveyQuestionsRepositoryInterface;

class SurveyAnswerDefinedEventHandler extends BaseEventHandler implements SurveyAnswerDefinedEventHandlerInterface 

    protected $rules = [];
    /**
     * @inheritDoc
     */
    public function subscribe(Dispatcher $dispatcher)
    
        $dispatcher->listen('vend.surveys.surveyanswerdefined.creating', __CLASS__.'@creating');
        $dispatcher->listen('vend.surveys.surveyanswerdefined.created', __CLASS__.'@created');

        $dispatcher->listen('vend.surveys.surveyanswerdefined.updating', __CLASS__.'@updating');
        $dispatcher->listen('vend.surveys.surveyanswerdefined.updated', __CLASS__.'@updated');

        $dispatcher->listen('vend.surveys.surveyanswerdefined.deleted', __CLASS__.'@deleted');
    

    /**
     * @inheritDoc
     */
    public function creating(SurveyQuestionsRepositoryInterface $questions, array $data)
    
        $this->setRules($questions);
        dd($this->rules);
    

    /**
     * @inheritDoc
     */
    public function created(SurveyAnswerDefined $surveyanswers)
    
        $this->flushCache($surveyanswers);
    

    /**
     * @inheritDoc
     */
    public function updating(SurveyAnswerDefined $surveyanswers, array $data)
    

        $this->setRules($questions);
        dd($this->rules);
    

    /**
     * @inheritDoc
     */
    public function updated(SurveyAnswerDefined $surveyanswers)
    
        $this->flushCache($surveyanswers);
    

    /**
     * @inheritDoc
     */
    public function deleted(SurveyAnswerDefined $surveyanswers)
    
        $this->flushCache($surveyanswers);
    

    /**
     * Flush the cache.
     *
     * @param  \vend\Surveys\Models\Surveyanswers  $surveyanswers
     * @return void
     */
    protected function flushCache(SurveyAnswerDefined $surveyanswers)
    
        $this->app['cache']->forget('vend.surveys.surveyanswerdefined.all');

        $this->app['cache']->forget('vend.surveys.surveyanswerdefined.'.$surveyanswers->id);
    


    private function setRules($questions)

        foreach($questions as $question)

            foreach($questions->controls as $control)

                $this->rules['control_' . $control->id] = $this->makeRules($control);
            

        
    

    private function makeRules($control)

        $rules = [];

        if($control->is_required)
            $rules[] = 'required';
        

        if($control->validation_rule == 'Text')

            if($control->min_length)
                $rules[] = 'min:' . $control->max_length;
            

            if($control->max_length)
                $rules[] = 'max:' . $control->max_length;
            

        


        if($control->validation_rule == 'Number')

            $rules[] = 'numeric';

            if($control->min_value)
                $rules[] = 'min:' . $control->max_length;
            

            if($control->max_value)
                $rules[] = 'max:' . $control->max_length;
            

        


    

【问题讨论】:

【参考方案1】:

您可以 (IMO) 使用模型事件,例如:保存时(适用于创建和更新)您可以调用 setCustomRules 方法来设置和验证规则,如下所示:

public static function boot()

    parent::boot();

    // This method will be called on creating and updating
    // but there are separate events for both methods so you
    // may use separate handlers for different events like : 
    // static::creating(...) static::updating(...)
    static::saving(function($user)
    
        // Set rules and validate here
    );

这应该在模型中,还有其他注册事件的方法,但我最喜欢这种方式。欲了解更多信息,请查看Laravel Website@Events

【讨论】:

如果我理解 laravel laravel.com/docs/5.1/lifecycle 中的请求生命周期,验证步骤发生在任何数据库操作之前。因此,如果有错误,Laravel 将生成错误,然后将用户发送到视图或将每个内容返回给控制器的方法。因此,如果验证发生在任何 SQL 操作之前,您的建议将导致验证两次,一次是默认 Laravel 步骤,然后是保存前的步骤。我在这里错过了什么? 不,如果您注册这些事件,那么它会以这种方式工作。例如,在引导方法中,如果您注册了creating(function()...),那么在创建新模型之前,该函数将被执行。如果您从该函数返回 false,则 create 将被中断,这意味着不会为无效数据保存新模型。你需要手动捕捉它。 我想我明白了。那么如何将 SurveyAnswerDefinedRepository 类注入到 save() 事件中,以便读取数据库中的规则? 将规则传递给该模型或从模型本身中获取规则,只需尝试一下,阅读文档以获取更多信息,我相信您可以做到 :-)跨度> 我想我跟着你。好吧,我希望我是 :) 我创建了创建、更新事件处理程序,并注入了允许我获取规则的类。如何设置规则或告诉 Laravel 现在进行验证?我的意思是我将如何触发验证器?我会用我的代码更新我的问题【参考方案2】:

迟到的答复

您也可以使用Model Mutators 并进行验证

例如

public function setFirstNameAttribute($value) 
    // validate $value e.g.:
    if (strlen($value) < 2) 
        throw new \Exception('name too short, 2 char minimum');
    

【讨论】:

以上是关于如何在 Laravel 中使用 setter 方法设置验证规则?的主要内容,如果未能解决你的问题,请参考以下文章

axios请求给getter setter方法而不是查询数据

如何保护 Laravel 模型属性

Silverlight:如何在 setter 中为样式使用绑定(或等效的解决方法)

laravel核心服务

如何在python中获取属性的setter方法的属性

在 laravel vue 中通过 axios post 发送对象数组