Laravel多重自定义验证

时间:2014-07-10 01:41:20

标签: php validation laravel

我想添加多个自定义验证,每个验证都是自己的文件。

到目前为止,我已将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 个答案:

答案 0 :(得分:5)

我通过制作所有单独的验证器特征来解决这个问题,因此我的一个自定义验证器可以简单地“使用”我的特征并仍然将它们分开。

我的验证员:

<?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, []);
});

答案 1 :(得分: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的对象。这意味着要么a)你需要检查数组值并弄清楚你想要验证的是什么,或者b)你需要在验证它时为数组添加一个标志或类型值。第二种可能更容易,也更健壮。例如:

// 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);
    }
});

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

答案 2 :(得分:-1)

使用Custom Validator创建一个类,例如:

<?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中的解析器Validator之前或其他文件中。

use Acme\Validators\CustomValidator as CustomValidator;

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