Reputation: 36189
I'd like to add multiple custom validation, each as their own file.
So far, I've modified my app/start/global.php
file to
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);
});
And each of my validation files would be in the /validators
as
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 ...
}
So how can I add multiple of these validators?
Upvotes: 3
Views: 3526
Reputation: 548
Create one class with Custom Validator for example:
<?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;
}
}
}
And before resolver Validator in app/routes.php for example or in other file.
use Acme\Validators\CustomValidator as CustomValidator;
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages);
});
Upvotes: -1
Reputation: 1418
I solved this by making all my separate validators traits, so my one custom validators can simply 'use' my traits and still keep them separated.
My validator:
<?php
use Illuminate\Validation\Validator as LaravelValidator;
class CustomValidator extends LaravelValidator {
use PhoneValidatorTrait;
}
My trait:
<?php
class PhoneValidatorTrait {
public function validateSomething(){ ... }
}
resolver:
<?php
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages, []);
});
Upvotes: 6
Reputation: 15760
My guess is that the call to Validator::resolver
simply sets a value if it's not already set, so the second and later calls are ignored.
What you really need is one call to Validator::resolver
and include your logic for choosing which validator to use in the closure. It would look something like this:
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);
}
});
The trick is goinge to be the if
test - I'm not sure what to do there. The first thing that comes to mind is to check the type of $data
:
if ($data instanceof Schedule) {
But the validator is going to receive an array instead of an object for $data
. So that means either a) you need to examine the array values and puzzle out what it is you're trying to validate, or b) you need to add a flag or type value to the array when you're validating it. The second is likely to be easier and a little more robust. For example:
// 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);
}
});
This is, unfortunately, not a very elegant solution. To improve it, you might create a library whose sole task is resolving the type of validator required.
Upvotes: 0