I am defining a Custom validator in my AppServiceProvider@boot as following
/* Custom unique value in set of fields validation */
Validator::extend('unique_in', function ($attribute, $value, $parameters, $validator) {
$validator_data = $validator->getData();
foreach ($parameters as $field) {
if ($value === array_get($validator_data, $field)) {
return false;
}
}
return true;
}, 'The :attribute cannot be same as any other field in this form.');
/* replace the :fields message string */
Validator::replacer('unique_in', function ($message, $attribute, $rule, $parameters) {
// I was doing this (this works)
// $message = str_replace(':field', implode(',',$parameters), $message);
// return $message;
//I want to do this (to get proper names for the fields)
$other = $this->getAttribute(array_shift($parameters));
return str_replace([':other', ':values'], [$other, implode(', ', $parameters)], $message);
});
Problem is instance of validator is not available to access getAttribute
.
getAttribute resolves the readable name for parameters
Is there to access validator instance in replacer?
Note that the closure in Validator::extend
has $validator
which is an instance of validator.
I got it working using getCustomMessage
and setCustomMessage
, but without using Validator::replacer
using Validator::extend
alone.
Validator::extend('unique_in', function ($attribute, $value, $parameters, $validator) {
$validator_data = $validator->getData();
$parameters = array_diff($parameters, [$attribute]);
$same = null;
$other = null;
foreach ($parameters as $field) {
if ($value === array_get($validator_data, $field)) {
$same[] = $field;
}
}
//No same values found , validation success
if (is_null($same)) {
return true;
}
// Get all Custom Attributes those are defined for this validator and replace with field in $same array and create a new $other array
$custom_attributes = $validator->getCustomAttributes();
foreach ($same as $attribute) {
$other[$attribute] = isset($custom_attributes[$attribute]) ? $custom_attributes[$attribute] : $attribute;
}
//Task of Validator:replacer is done right here.
$message = 'The :attribute cannot have same value ":value" as in :fields';
$message = str_replace([':value',':fields'], [$value ,implode(', ', $other)], $message);
$validator->setCustomMessages(array_merge($validator->getCustomMessages(), ['unique_in' => $message]));
return false;
});
Thanks,
K