Laravel 5.3 set second attribute name in custom validation rule - laravel

I have the following custom validation rule...
Validator::extend('empty_with', function ($attribute, $value, $parameters, $validator) {
$other = array_get($validator->getData(), $parameters[0], null);
return ($value != '' && $other != '') ? false : true;
}, "The :attribute field is not required with the :other field.");
And am using it like...
$validator = Validator::make($request->all(), [
'officer' => 'sometimes|integer',
'station' => 'empty_with:officer,|integer',
]);
The current error message am getting is
The station field is not required with the:otherfield.
Versus what I would like to have;
The station field is not required with the officer field.
How do I set a the second parameter 'officer' in the error message, the same way :attribute is...??

You'll need to add in a custom replacer to go with your custom validation rule. See 'Defining the error message' here.
\Validator::replacer('empty_with', function ($message, $attribute, $rule, $parameters) {
return str_replace(':other', $parameters[0], $message);
});
This code tells Laravel that when the empty_with rule fails, the message should be run through that closure before being passed back to the user. The closure performs a simple string replacement and returns the amended error message.
For the most part, each validation rule has its own replacement rules for messages since it's dependent on the specific attributes and their order. Although :other being replaced with the first parameter happens for a few rules, it's not automatic and is defined explicitly for each rule that uses it. It's worth looking in the Illuminate\Validation\Concerns\ReplacesAttributes trait to get an idea of how Laravel deals with replacement for its built-in rules.

Related

Use `trans_choice()` in request validation messages with validation rule parameter

I need a request validation rule to return a custom message upon failure, and since the field being validating is an array with a min:x rule i'd like to have a custom message for both singular and plural variations.
I'm just wondering how to pass to the trans_choice() function the :min parameter from the validation rule:
Translation file:
'array' => [
'field' => [
'min' => 'You need to select at least one item.|you need to select at least :min items',
],
],
Request message() method:
public function messages() {
'my.array.field.min' => trans_choice('translations::array.field.min', ???),
}
It seems like there's nothing built into Laravel to use trans_choice whenever you can pluralise a translation string.
A way you could solve that is by temporarily (or permanently, whatever fits your use-case) changing the replacer for the min rule to something like this:
Validator::replacer('min', function ($message, $attribute, $rule, $parameters, $validator) {
$minValue = $parameters[0];
$message = Str::contains($message, '|')
? trans_choice($message, $minValue)
: $message;
return str_replace(':min', $minValue, $message);
});
Or by extending the Validator factory to work in your favour, but since that requires you to change many of it's methods I don't really recommend that.

Laravel validation rules - how optional, but only if another condition is true

How can I make a custom rule using Validation, so that the field can be nullable 'since' call function the result is true, otherwise, the field becomes required.
Of course I tried to use the 'nullable', but even if the field is empty, the Validation should execute the checkAreasDiff() function to validate that the field can be empty during the update.
In my controller, I created a function:
private function validator_update(array $data) {
\Validator::extend('areas_diff', function($attribute, $value, $parameters, $validator) {
return checkAreasDiff();
}, 'VALIDATOR AREAS_DIFF OK.');
/**
* RULES
*/
$rules = [
'fiscalizoarea' => 'areas_diff',
];
/**
* Return \Validator
*/
return \Validator::make($data, $rules, $msgs);
}
If I understand the question correctly, you want one field to be required only if another is not null?
There is a Laravel rule for that already: required_with.
required_with:foo,bar,...
The field under validation must be present and not empty only if any
of the other specified fields are present.
Or, if I'm getting your logic back to front: required_without
required_without:foo,bar,...
The field under validation must be present and not empty only when any
of the other specified fields are not present.

Array number/position in custom Laravel validation messages

When validating arrays in Laravel and using custom error messages, is there any way to access the array number/position that is throwing the validation failure?
Trying to manipulate :attribute or :key in the messages array of the Request doesn't work as the placeholders are later translated (read: they aren't the actual variables)
I am trying to present a message like:
object.property.*.required => 'The property on object # is required'
Otherwise you end up with something like:
object.property.3 is required
I'd like to grab the number so I can present a friendlier and more descriptive message.
Well, this can be achieved by the replacer method on the Validator facade. Add the replacer in AppServiceProvider#boot method.
//...
public function boot()
{
Validator::replacer('required', function ($message, $attribute, $rule, $parameters) {
if (str_contains($message, ':nth') && preg_match("/\.(\d+)\./", $attribute, $match)) {
return str_replace(":nth", $match[1]+ 1, $message);
}
return $message;
});
}
//...
The custom validation message for the attribute must contain the palceholder :nth
object.property.*.required => 'The property on object :nth is required'

Laravel custom validation: only validate input if input given

So I followed this tutorial to learn how to upload images with Laravel using Vue: Image upload and validation using Laravel and VueJs
Everything works fine, but I want to make the image upload optional. Now the custom validation fails for the AppServiceProvider. if it does not have any input then i get this error
trying to access an attribute inside an array that does not exist. Undefined offset: 1
I could avoid the error by asking
if (request('image'))
In the controller and applying the validation for the other fields only if no image is given. However, this gets incredibly messy.
So I am looking for a way to get the custom validation rule working if there is no input. Or is that the wrong way?
Here is the custom validation rule:
public function boot()
{
Validator::extend('image64', function ($attribute, $value, $parameters, $validator) {
$type = explode('/', explode(':', substr($value, 0, strpos($value, ';')))[1])[1];
if (in_array($type, $parameters)) {
return true;
}
return false;
});
Validator::replacer('image64', function($message, $attribute, $rule, $parameters) {
return str_replace(':values',join(",",$parameters),$message);
});
}
In some situations, you may wish to run validation checks against a field only if that field is present in the input array. To quickly accomplish this, add the sometimes rule to your rule list:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
In the example above, the email field will only be validated if it is present in the $data array.
Reference: Conditionally Adding Rules
Laravel provides a validation called 'nullable' in case other validation rules should not be run if the given value is null: A Note On Optional Fields

Laravel - "Other" place holder not accepting friendly names in validation message

In Laravel,
I am using custom validation in my project to check whether mininum area having smaller value than maximum area. Just created the validation in Validator library
public function validate_less_than($attribute, $value, $parameters)
{
$other_value = $this->attributes[$parameters[0]];
if(!empty($value) && !empty($other_value))
return $value <= $other_value;
else
return true;
}
added validation message for "less_than", in language file.
'less_than' => "The :attribute must be less than :other value",
and added replace placeholder function in validator library, to replace the :other placeholder
protected function replace_less_than($message, $attribute, $rule, $parameters)
{
return str_replace(':other', $parameters[0], $message);
}
my field names are like "min_area", "max_area", so I don't want this field names in validation message, so i have added friendly names for these fields in language files. but ":other" placeholder not taking the friendly names which is specified in validation language file. is it only possible for ":attribute" placeholder?
It's hard coded in validator.php at around line 856 (in current version 3.2.12).
You could run it from your replacer tough.
protected function replace_less_than($message, $attribute, $rule, $parameters)
{
return str_replace(':other', $this->attribute($parameters[0]), $message);
}
Note the $this->attribute().

Resources