Laravel多个自定义验证

3
我想添加多个自定义验证,每个都有自己的文件。
到目前为止,我已经修改了我的app/start/global.php文件。

global.php

ClassLoader::addDirectories(array(
    app_path().'/commands',
    app_path().'/controllers',
    app_path().'/models',
    app_path().'/database/seeds',
    app_path().'/validators'        // <--- Added this folder
));

// Only the first resolver works. 
// I cannot seem to have multiple of these files

Validator::resolver(function($translator, $data, $rules, $messages) 
{
    return new ScheduleValidator($translator, $data, $rules, $messages);
});

Validator::resolver(function($translator, $data, $rules, $messages) 
{
    return new UserValidator($translator, $data, $rules, $messages);
});

我的每个验证文件都会在/validators中。

ScheduleValidator.php

class ScheduleValidator extends Illuminate\Validation\Validator
{
    protected $implicitRules = array('Required', 'RequiredWith', 'RequiredWithout', 'RequiredIf', 'Accepted', 'RequiredWithoutField');
    public function __construct(\Symfony\Component\Translation\TranslatorInterface $translator, $data, $rules, $messages = array())
    {
        parent::__construct($translator, $data, $rules, $messages);
        $this->isImplicit('fail');
    }

    /**
    * Validates type to be of the type 'common', 'template', or 'revision'
    */
    public function validateTypeSchedule($attribute, $value, $parameters = null)
    {
        $valid_types = ['template', 'common', 'revision'];
        return in_array($value, $valid_types);
    }

    // and the other validators ...
}

那么我该如何添加多个验证器呢?

3个回答

6
我通过将所有单独的验证器制作成traits来解决了这个问题,这样我的一个自定义验证器就可以简单地“使用”我的traits并保持它们分开。
我的验证器:
<?php

use Illuminate\Validation\Validator as LaravelValidator;

class CustomValidator extends LaravelValidator {
    use PhoneValidatorTrait;

}

我的特点:

<?php

class PhoneValidatorTrait {
    public function validateSomething(){ ... }
}

解析器:

<?php

Validator::resolver(function($translator, $data, $rules, $messages)
{
    return new CustomValidator($translator, $data, $rules, $messages, []);
});

0

我的猜测是对于Validator::resolver的调用只会在值未设置时进行设置,因此第二次及以后的调用将被忽略。

你真正需要的是一次对Validator::resolver的调用,并在闭包中包含选择要使用哪个验证器的逻辑。它看起来应该像这样:

Validator::resolver(function($translator, $data, $rules, $messages) 
{
    // perform a test to figure out what kind of validator to return
    if ($schedule) {
        return new ScheduleValidator($translator, $data, $rules, $messages);
    } else {
        return new UserValidator($translator, $data, $rules, $messages);
    }
});

关键在于 if 测试 - 我不确定该怎么做。首先想到的是检查 $data 的类型:
if ($data instanceof Schedule) {

但验证器将会接收一个数组而不是一个对象,用于 $data。那么这意味着你需要查看数组的值并理解你要验证的内容,或者在验证时向数组添加一个标志或类型值。第二种方法可能更简单和更健壮。例如:

// in the Schedule controller
$data = Input::all();
$data["type"] = "schedule";
$validator = Validator::make($data, $rules);

// in global.php
Validator::resolver(function($translator, $data, $rules, $messages) 
{
    // perform a test to figure out what kind of validator to return
    if ($data["type"]=="schedule") {
        return new ScheduleValidator($translator, $data, $rules, $messages);
    } else {
        return new UserValidator($translator, $data, $rules, $messages);
    }
});

很遗憾,这不是一个非常优雅的解决方案。为了改进它,您可以创建一个库,其唯一任务是解析所需验证器的类型。


好的,谢谢,我会尝试一下。但是为什么没有一个简单的方法来做这个呢?我认为这不是一个非常不切实际的要求。特别是当项目变得庞大时,将自定义验证与其模型分开是很有必要的。 - Kousha
是的,我不能说我不同意你。如果你对基于模型的验证感兴趣,有一个 Laravel 包可以处理模型中的验证。我一时想不起它的名字。 - Kryten

-1
创建一个自定义验证器的类,例如:
<?php namespace Acme\Validators;

use Illuminate\Validation\Validator as Validator;
use DB;
use Input;
use Request;

class CustomValidator extends Validator {

    public function validateUniqueWith($attribute, $value, $parameters)
    {
        $table = $parameters[0];

        $query = DB::table($table)
            ->where($parameters[1], Input::get($parameters[1]))
            ->where($attribute, $value);

        if (isset($parameters[3]))
        {
            list($idColumn, $id) = $this->getUniqueIds($parameters);
            $query->where('id', '!=', $idColumn);
        }

        if($query->count() > 0)
        {
            return false;
        }

        return true;
    }

    public function validateDateSame($attribute, $value, $parameters)
    {
        $this->requireParameterCount(1, $parameters, 'date_same');

        if ( ! ($date = strtotime($parameters[0])))
        {
            return strtotime($value) >= strtotime($this->getValue($parameters[0]));
        }
        else
        {
            return strtotime($value) >= $date;
        }
    }

    public function validateDni($attribute, $value, $parameters)
    {
        if(strlen($value)<9) {
            return false;
        }

        $value = strtoupper($value);

        $letra = substr($value, -1, 1);
        $numero = substr($value, 0, 8);

        // Si es un NIE hay que cambiar la primera letra por 0, 1 ó 2 dependiendo de si es X, Y o Z.
        $numero = str_replace(array('X', 'Y', 'Z'), array(0, 1, 2), $numero);

        $modulo = $numero % 23;
        $letras_validas = "TRWAGMYFPDXBNJZSQVHLCKE";
        $letra_correcta = substr($letras_validas, $modulo, 1);

        if($letra_correcta!=$letra) {
            return false;
        }
        else {
            return true;
        }
    }

}

在 app/routes.php 或其他文件中,先使用解析器验证器。

use Acme\Validators\CustomValidator as CustomValidator;

Validator::resolver(function($translator, $data, $rules, $messages)
{
    return new CustomValidator($translator, $data, $rules, $messages);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接