Skip to content

Instantly share code, notes, and snippets.

@jlem
Last active November 23, 2016 19:00
Show Gist options
  • Save jlem/a5498ab3498eebb67b8f to your computer and use it in GitHub Desktop.
Save jlem/a5498ab3498eebb67b8f to your computer and use it in GitHub Desktop.
Sloppy Validation Wrapper
<?php
// Assign this to models and implement these methods
interface ShouldBeValidated
{
/**
* Returns an array of key => value rules (as per normal Laravel validation)
*
* @return array
*/
public function getValidationRules();
/**
* Returns an array of key => value messages (as per normal Laravel validation)
*
* @return array
*/
public function getValidationMessages();
}
// Base class wrapper for Laravel's validator
// Extend this for each form, and define the
// rules and messages in the specified abstract methods
abstract class Validator {
protected $factory;
protected $models;
public function __construct(Illuminate\Validation\Factory $factory)
{
$this->factory = $factory;
}
/**
* Binds a ShouldBeValidated instance for rule/message merging later
*
* @return void
*/
public function bindModel(ShouldBeValidated $model)
{
$this->models[] = $model;
}
/**
* Wrapper for Laravel's actual validator
*
* @param array $input
* @return Illuminate\Validation\Validator
*/
public function make(array $input)
{
$validations = $this->mergeValidations();
return $this->factory->make($input, $validations['rules'], $validations['messages']);
}
/**
* Merges each ShouldBeValidated's rules and messages together with the form's own
*
* @return array
*/
protected function mergeValidations()
{
$rules = [];
$messages = [];
foreach($this->models as $model) {
$rules[] = $model->getValidationRules();
$messages[] = $model->getValidationMessages();
}
$rules[] = $this->getRules(); // Override model rules with form rules
$messages[] = $this->getMessages(); // Override model messages with form messages
return [
'rules' => call_user_func_array('array_replace', $rules),
'messages' => call_user_func_array('array_replace', $messages)
];
}
/**
* Returns an array of key => value rules (as per normal Laravel validation)
*
* @return array
*/
abstract public function getRules();
/**
* Returns an array of key => value messages (as per normal Laravel validation)
*
* @return array
*/
abstract public function getMessages();
}
@jlem
Copy link
Author

jlem commented Jan 8, 2015

FYI, this is a good chance to illustrate when to use abstract vs interface.

The parent class mergeValidations() won't work unless its children have implementations of specific methods (this is the template method pattern!, so we need to enforce this contract somehow.

Since Im not injecting this behavior, and instead inheriting it, interfaces won't help me enforce this contract. But abstract classes will. This is an "internal contract".

Meanwhile the models ARE being injected, thus have an "external contract". This external contract can be secured with nothing more than an interface, so that's what we use.

In short: use abstract contracts for inheritance (i.e. internal enforcement), and use interface contracts for composition (i.e. external enforcement).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment