Skip to content

Instantly share code, notes, and snippets.

@thepsion5
Last active November 10, 2016 07:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thepsion5/9bccc8d05a36ef2c4453 to your computer and use it in GitHub Desktop.
Save thepsion5/9bccc8d05a36ef2c4453 to your computer and use it in GitHub Desktop.
Demonstration of a simple wrapper for Laravel's Validator that allows rules to be altered based on input before validating and exceptions as transports for validation errors
<?php
use Illuminate\Support\MessageBag,
Illuminate\Validation\Factory;
/**
* A simple wrapper for Laravel's native validator. Allows
* validation rules to be modified pre-validation based on
* input and can be used to throw an exception with the
* input and validation failures
*/
abstract class LaravelValidator
{
/**
* Validation messages to use per rule when failures occur
* @var array
*/
protected $messages = array();
/**
* Validation rules to be tested against the provided input
* @var array
*/
protected $rules = array();
/**
* Any failures from the last validation
* @var MessageBag
*/
protected $errors;
public function __construct(Factory $validatorFactory)
{
$this->factory = $validatorFactory;
$this->errors = new MessageBag;
}
/**
* This function can be overridden to modify the validation rules based on input
* for example to exclude an id from a uniqueness constraint
* @param array $input The input to be validated
* @param array $rules The initial rules
* @return array The modified rules based on input
*/
protected function modifyRules(array $input, array $rules)
{
return $rules;
}
/**
* Performs the actual validation
* @param array $input The input to validate
* @return bool True if validation passes, false otherwise
*/
public function validate(array $input)
{
$rules = $this->modifyRules($input, $this->rules);
$validator = $this->factory->make($input, $rules, $this->messages);
$passes = $validator->passes();
$this->errors = ($passes) ? new MessageBag : $validator->messages();
return $passes;
}
/**
* Returns any errors that occurred during the last validation attempt
* @return MessageBag
*/
public function getErrors()
{
return $this->errors;
}
/**
* Performs validation and throws a ValidationFailureException with errors
* and input if validation fails
* @param array $input
*/
public function assertValid(array $input)
{
if(!$this->validate($input)) {
$this->throwValidationException($input, $this->errors);
}
}
/**
* Creates, configures, and throws a validation exception
* @param array $input The validated input
* @param MessageBag $errors The validation failures
* @throws ValidationFailureException The thrown exception
*/
protected function throwValidationException(array $input, MessageBag $errors)
{
$exception = new ValidationFailureException('Validation Failed.');
$exception->setErrors($errors)->setInput($input);
throw $exception;
}
}
<?php
class SampleUserValidator extends LaravelValidator
{
protected $rules = array(
'username' => 'required|min:8',
'password' => 'required|min:8',
'first' => 'required|min:2',
'last' => 'required|min:2',
'email' => 'required|email'
);
protected function modifyRules(array $input, array $rules)
{
$id = isset($input['id']) ? $input['id'] : null;
$rules['username'] .= ($id) ? "|unique:users,username,$id" : '|unique:users';
$rules['email'] .= ($id) ? "|unique:users,email,$id" : '|unique:email';
return $rules;
}
}
<?php
use Illuminate\Support\MessageBag;
/**
* An exception class that acts as a transport for validation input and failures
*/
class ValidationFailureException extends InvalidArgumentException
{
protected $errors;
protected $input = array();
public function __construct($message = '', $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->errors = new MessageBag;
}
public function setErrors(MessageBag $errors)
{
$this->errors = $errors;
return $this;
}
public function getErrors()
{
return $this->errors;
}
public function setInput(array $input)
{
$this->input = $input;
return $this;
}
public function getInput()
{
return $this->input;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment