Skip to content

Instantly share code, notes, and snippets.

@kmuenkel
Last active August 9, 2019 05:32
Show Gist options
  • Select an option

  • Save kmuenkel/094ed4ced4365fbc8f9483ddb8d9bae7 to your computer and use it in GitHub Desktop.

Select an option

Save kmuenkel/094ed4ced4365fbc8f9483ddb8d9bae7 to your computer and use it in GitHub Desktop.
Laravel Parameter-Specific Custom Validation Messages
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Overrides\Illuminate\Validation\Factory as FactoryOverride;
/**
* Class AppServiceProvider
* @package App\Providers
*/
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->validatorExtensions();
}
/**
* Custom extensions to the Validator Facade
*/
protected function validatorExtensions()
{
//Borrowed from Illuminate\Validation\ValidationServiceProvider::registerValidationFactory()
$this->app->singleton('validator', function ($app) {
$validator = new FactoryOverride($app['translator'], $app);
if (isset($app['db'], $app['validation.presence'])) {
$validator->setPresenceVerifier($app['validation.presence']);
}
return $validator;
});
}
}
<?php
namespace App\Overrides\Illuminate\Validation;
use Illuminate\Validation\Factory as BaseFactory;
/**
* Class Factory
* @package App\Overrides\Illuminate\Validation
*/
class Factory extends BaseFactory
{
/**
* Override so that the override of the Validator class is returned instead of the original
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return Validator|\Illuminate\Validation\Validator|mixed
*/
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
{
if (is_null($this->resolver)) {
return new Validator($this->translator, $data, $rules, $messages, $customAttributes);
}
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
}
}
<?php
namespace App\Overrides\Illuminate\Validation;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationRuleParser;
use Illuminate\Validation\Validator as BaseValidator;
/**
* Class Validator
* @package App\Overrides\Illuminate\Validation
*/
class Validator extends BaseValidator
{
/**
* @var array
*/
protected $parameters = [];
/**
* @param string $attribute
* @param string $rule
* @param array $parameters
*/
protected function addFailure($attribute, $rule, $parameters)
{
//Cheat the process-flow a little bit, and make these values available to the override for the custom error
//message identification process without having to alter the signature of too many parent methods
$this->parameters = $parameters;
parent::addFailure($attribute, $rule, $parameters);
}
/**
* Most of this method mirrors the original parent, overridden to add support for parameter-specific error messages
*
* @param string $attribute
* @param string $lowerRule
* @param null $source
* @return null|string
*/
protected function getFromLocalArray($attribute, $lowerRule, $source = null)
{
//Use a placeholder indicator of the existence of parameters so that they don't need to be known in advance
$paramPlaceholder = ':params';
$source = $source ?: $this->customMessages;
$keys = [
"$attribute.$lowerRule$paramPlaceholder",
"$attribute.$lowerRule",
"$lowerRule$paramPlaceholder",
$lowerRule
];
foreach (array_keys($source) as $sourceKey) {
list($rule, $sourceParams) = ValidationRuleParser::parse($sourceKey);
$hasAllSourceParams = count(array_intersect($sourceParams, $this->parameters)) == count($sourceParams);
//If the custom message key specifies parameters, replace it with out placeholder for comparison
$testKey = preg_replace('/(.+?)(\:.+)/', "$1$paramPlaceholder", $sourceKey);
foreach ($keys as $key) {
if (Str::is($testKey, $key) && $hasAllSourceParams) {
$message = $source[$sourceKey];
return $message;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment