Laravel custom rule pass array attribute - laravel

I have a custom rule and not sure how to pass one array attribute to that rule.
Following is my formRequest rules method
'reservedProducts' => ['bail', 'array'],
'reservedProducts.*.productId' => ['required',new CheckForStockAvailability()],
There is another hidden field passed in array named reservedProducts[locationId], how do I pass that locationId to CheckForStockAvailability rule?
I do not want to pass all request attributes but instead just pass the locationId.
Thank you

For example, consider the following rule that specifies that a credit card number is required if the payment_type has a value of cc:
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc' ]);
If this validation rule fails, it will produce the following error message:
The credit card number field is required when payment type is cc.
Instead of displaying cc as the payment type value, you may specify a more user-friendly value representation in your resources/lang/xx/validation.php language file by defining a values array:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
After defining this value, the validation rule will produce the following error message:
The credit card number field is required when payment type is credit
card.

in your formRequest
public function rules()
{
return [
'reservedProducts' => [
'bail', 'array'
],
'reservedProducts.*' => [
'required',
function($attribute, $value, $fail){
var_dump($value); // -> reservedProducts.0 {"productId":2}
preg_match('/reservedProducts.(.*?) {/', $value, $match);
$locationId = (int)$match[1]; // -> 0
}
],
];
}

Related

Validate a single variable or an array in Laravel

I want to validate a single variable like this $name = "example name" but I didn't a way to handle it then I decided to convert it to an array like this $nameArr = ['name' => 'example name'];, the validator is
$rules =
$this->validate($nameArr, [
'name' => 'required|max:10|regex:/^[a-zA-Z0-9]+$/u',
], [
'name.required' => 'name is empty',
'name.max' => 'name must be more less than 10 letters',
'name.regex' => 'invalid name'
]
);
but the Laravel gives this error
Argument 1 passed to App\Http\Controllers\Controller::validate() must be an instance of Illuminate\Http\Request, string given
Correct, the validate function on Controller comes from Illuminate\Foundation\Validation\ValidatesRequests and requires the first paramter to be a request object.
If you want to validate an array, you will have to create the validator manually.
$validator = Validator::make($nameArr,
[
'name' => 'required|max:10|regex:/^[a-zA-Z0-9]+$/u',
],
[
'name.required' => 'name is empty',
'name.max' => 'name must be more less than 10 letters',
'name.regex' => 'invalid name'
]
);
if ($validator->fails()) {
dd($validator->errors());
}
After knowing that the parameter is passed as route url param, I would like to add another option which Laravel provides to validate :
Route::get('user/{name}', 'UserProfileController#getByName')
->where([ 'name' => '[a-z]{10,}' ]);
The where method validates the route param based on provided regular expressions. So [a-z]{10,} will make sure the name is present with 10 or more characters.
See documentation for more

How to validate several rules with 'required_if' on Laravel 5.5?

I am trying to validate the 'uuid' field so that it is mandatory if the 'typeUUID' field is marked 'type1'.
$validator = Validator::make($request->all(), [
'uuid' => 'required_if:typeUUID,==,type1|alpha_dash|size:36',
]);
If I select the value 'type1' it indicates that the field is mandatory, and when I set another value that is not mandatory, it validates' alpha_dash 'and' size: 36 and does not accept the field since it is sent empty.
What is the right way?
I know I could do it with a condition by checking the type at the beginning and then applying one or more rules. But I would like to know the correct way to do it.
I found the solution, is to add the rule 'nullable' after the rule 'required_if'.
$validator = Validator::make($request->all(), [
'uuid' => 'required_if:typeUUID,==,type1|nullable|alpha_dash|size:36',
]);

Laravel - exclude current email from unique validation

I am trying to use unique on an email address in Laravel 5.5 validation like this..
$rules = [
'email' => 'email|unique:users,email,
];
This is working and is checking the 'users' table in the 'email' column
But if the email address is the same as the currently saved one then this also fails validation.
Is there a way I can add an exception rule to the validation to ignore $user-email?
The unique rule takes a third parameter: a record to ignore, see "Forcing A Unique Rule To Ignore A Given ID".
Pass in the ID of the record you do not wish to be included in the unique test, e.g:
$rules = [
'email' => 'email|unique:users,email,' . $user->id
];
THIS IS AN EASY SOLUTION
Just add $this->route('id') as the third parameter
if your route was defined like this:
Route::put('{company}', 'CompanyController#update')
->name('update');
then your parameter name is "company"
So in your FormRequest:
public function rules()
{
$rules = [
'url' => [
'required',
'url',
'unique:companies,url,'.$this->route('company') ?? 0
],
];
// dd($rules); << check yourself
return $rules;
}
This FormRequest works the same for insert or update.
this line will instruct to ignore "0" in case of insert
$this->route('company') ?? 0

How do the conditions for validation in Laravel

Just sorry for the dumb question , I know what it is in the documentation . But the documentation does not normally understand how to implement it .
Let's say there is a rule :
public function rules()
{
return [
'title' => 'required|max:15',
'author' => 'required|max:15',
];
}
and it is usually used in the form " Edit " , say the user when editing a product , exceeded character limit of 15 , then leave the message " You have exceeded the character limit ."
PS please show a simple example , he 'll take care of that next to nothing.
Looks like you're using FormRequest for validation. In that case you can add another method named messages() to your request class and return the custom messages from there, following is the example:
public function messages()
{
return [
'required' => 'The attribute: field cannot be left blank',
];
The above example will replace the standard error message the attribute: field is required. with our custom message for all occurrences of required rule, where the attribute: denotes the name of the field under validation.
But if you want to further customise it on per field basis. You can use the dot (.) notation like this:
public function messages()
{
return [
'title.required' => 'The Title must be filled',
];
You're looking for this link in the docs.
As the docs say, define an array of messages that map to the rules, and pass them into the validator. Like so
$rules = [ 'title' => 'max:15' ]
$msgs = [ 'max' => 'Exceeded char limit or whatever!' ]
Validator::make($input, $rules, $msgs);

Using form request specific custom validation attributes

Using Laravel's localization (http://laravel.com/docs/5.1/localization) I have created some custom validation attributes to provide friendlier validation errors (for instance, 'First Name' instead of first name etc).
I am using form requests (http://laravel.com/docs/5.1/validation#form-request-validation) in order to validate user submissions and there are scenarios where I would like to provide store-specific custom validation attributes (for instance, I may have a 'name' field that is Brand Name in one context, and Product Name in another).
The messages() method allows me to specify validation rule specific message overrides, but that isn't ideal as it's not the validation message as such we need to override, just the attribute name (for example, if we have 5 validation rules for 'email', we have to provide 5 overrides here, rather than one override for, let's say, Customer Email).
Is there a solution to this? I note references to formatValidationErrors() and formatErrors() in the Laravel documentation, but there is not really any information on how to correctly override these, and I've not had much luck in trying.
You can override the attribute names, which is defaulting to whatever the field name is.
With form request
In your form request class override the attributes() method:
public function attributes()
{
return [
'this_is_my_field' => 'Custom Field'
];
}
With controller or custom validation
You can use the 4th argument to override the field names:
$this->validate($request, $rules, $messages, $customAttributes);
or
Validator::make($data, $rules, $messages, $customAttributes);
Simple working example
Route::get('/', function () {
// The data to validate
$data = [
'this_is_my_field' => null
];
// Rules for the validator
$rules = [
'this_is_my_field' => 'required',
];
// Custom error messages
$messages = [
'required' => 'The message for :attribute is overwritten'
];
// Custom field names
$customAttributes = [
'this_is_my_field' => 'Custom Field'
];
$validator = Validator::make($data, $rules, $messages, $customAttributes);
if ($validator->fails()) {
dd($validator->messages());
}
dd('Validation passed!');
});
As detailed in my question, I was looking for a way to provide specific form request stores (http://laravel.com/docs/5.1/validation#form-request-validation) with custom attribute names.
The Laravel documentation only covers two methods for Requests in this context - rules() and authorize(). I was aware there is a messages() method to provide validation specific custom error messages, but it also appears there is an attributes() method, which fits my requirements exactly:
public function attributes()
{
return [
'name' => 'Product Name'
]
}
This overrides the attribute name in the context of my store.

Resources