Laravel 5.2 required_without_all Request Issue - validation

I'm having an issue with required_without_all. I have three elements, and at least one should be filled. My file input's name is image[]. Adding an image but leaving title and body empty still results in a validation error, even though it shouldn't.
Any thoughts on what I'm doing wrong?
public function rules()
{
return [
'title' => 'required_without_all:body,image.*',
'body' => 'required_without_all:title,image.*',
'image.*' => 'required_without_all:body,title',
];
}
public function messages()
{
return [
'title.required_without_all' => 'At least one field is required',
'body.required_without_all' => 'At least one field is required',
'image.*.required_without_all' => 'At least one field is required',
];
}

Answered here: https://stackoverflow.com/a/39089295/2101328
Basically, add image as an array and remove the * from the rules.
There was also a bug in Laravel 5.3 that prevented similar from working; see this thread: https://github.com/laravel/framework/issues/15044#issuecomment-244364706
public function rules()
{
return [
'title' => 'required_without_all:body,image',
'body' => 'required_without_all:title,image',
'image' => 'array',
'image.*' => 'required_without_all:body,title',
];
}

Related

The unique Rule validation is not applied

I am using laravel 9.
And I have this very simple validation rule (form request validation):
public function rules()
{
return [
'first_name' => 'required|max:50',
'last_name' => 'required|max:50',
'email' => [
'email',
Rule::unique('unknown_table')->where(function ($query) {
return $query->where('library_id', $this->library->id);
})
],
.......
What I do not understand is why my post is working with this table name "unknown_table", because this table really does not exist. I expected an exception but nothing happens !
Is this rule correctly written ?
I have understood my error. The "email" validation was twice in the rule array ! And it was the last one which was used of course.

Laravel FormRequest is modifying the input

I am having trouble using the Laravel Validator to validate some data. The validator is modifying properties of the input to null.
The data passed to be validated is a mix of array and objects (in this case, a model instance).
Just for clarification: I know how to use FormRequest in controllers, I am full aware that Laravel would inject the FormRequest in the methods, and FormRequest is primaly to be used to validate user data, etc, etc. The point is why the validator need to modify the data I sent to validation?
Here's an example that you can directly paste in a php artisan tinker session:
$rules = [
'users' => [
'required',
'array',
'min:1',
],
'users.*' => [
'required',
],
'users.*.name' => [
'required',
'string',
'max:255',
],
'users.*.age' => [
'required',
'integer',
],
'users.*.best_friend' => [
'required',
],
];
$data = [
'users' => [
(new \App\Models\User)->forceFill([
'name' => 'USER #1',
'age' => 30,
'best_friend' => (new \App\Models\User)->forceFill(['name' => 'User X'])
]),
],
];
echo 'BEFORE: ' . data_get($data, 'users.0.name'); // USER #1
$validator = Validator::make($data, $rules);
echo 'AFTER: ' . data_get($data, 'users.0.name'); // NULL
dd($data);
OK, the data PASSES. But the problem is that the validation modified the variable $data, setting null to the fields with these patterns: users.*.name, users.*.age and users.*.best_friend.
If I dare to validate any model attribute, it sets to null.
I debugged and I reached the source of the modification:
/vendor/laravel/framework/src/Illuminate/Validation/ValidationData.php:42:
/**
* Gather a copy of the attribute data filled with any missing attributes.
*
* #param string $attribute
* #param array $masterData
* #return array
*/
protected static function initializeAttributeOnData($attribute, $masterData)
{
$explicitPath = static::getLeadingExplicitAttributePath($attribute);
$data = static::extractDataFromPath($explicitPath, $masterData);
if (! str_contains($attribute, '*') || str_ends_with($attribute, '*')) {
return $data;
}
// here some debug info:
// $explicitPath="users"
// $attribute="users.*.name"
// $data=User
return data_set($data, $attribute, null, true);
}
I know data_set modifies by reference.
But I could not understand why the code modifies the data if there is data already there. Should not it check for data before setting to null?
The validator is making the validated properties of my model to be null. Why and how to fix?
Maybe a different approach? Maybe this could be considered an bug/improvement for the Illuminate lib?
Any help would be apreciated.
VERSIONS:
Laravel Framework 9.33.0
PHP 8.1.2
Laravel transforms the keys from your validation rules: name and age. But that didn't work as expected because users are objects. To solve that you need to call toArray() after forceFill
$data = [
'users' => [
(new \App\Models\User) -> forceFill([
'name' => 'USER #1',
'age' => 30,
'best_friend' => (new \App\Models\User) -> forceFill(['name' => 'User X'])
])->toArray(),
]
];
If you need validation for best_friend.name you need to call toArray() on that too. But without validation you will get the object as it is.

Laravel Requests Validation rules only if value is not null?

I've created a request for my update method called CandidateProfileUpdateRequest.php:
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'photo' => ['mimes:jpeg,png,jpg,gif,bmp', 'max:4096'],
'video_one' => ['mimes:mp4,mov,ogg,qt', 'max:30720'],
'video_two' => ['mimes:mp4,mov,ogg,qt', 'max:30720'],
'video_three' => ['mimes:mp4,mov,ogg,qt', 'max:30720'],
'resume' => ['mimes:doc,docx,pdf', 'max:4096'],
'job_title' => ['required'],
];
}
public function messages()
{
return [
'photo.max' => 'The photo may not be greater than 4MB.',
'video_one.max' => 'The video may not be greater than 30MB.',
'video_two.max' => 'The video may not be greater than 30MB.',
'video_three.max' => 'The video may not be greater than 30MB.',
'resume.max' => 'The resume may not be greater than 4MB.',
];
}
For these 4 fields that aren't required photo, video_one, video_two, video_three,
I only want to apply these rules, if a file is being uploaded in either of these form fields.
So for example if video_two is empty i.e. the User isn't uploading anything here, and clicks Update, it shouldn't return any rules for video_two. Is this possible?
Check out the sometimes rule.
In some situations, you may wish to run validation checks against a field only if that field is present in the data being validated. To quickly accomplish this, add the sometimes rule to your rule list:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'photo' => ['mimes:jpeg,png,jpg,gif,bmp', 'max:4096'],
'video_one' => ['mimes:mp4,mov,ogg,qt', 'max:30720'],
'video_two' => ['sometimes', 'mimes:mp4,mov,ogg,qt', 'max:30720'],
// ^^^^^^^^^^^
'video_three' => ['mimes:mp4,mov,ogg,qt', 'max:30720'],
'resume' => ['mimes:doc,docx,pdf', 'max:4096'],
'job_title' => ['required'],
];
}
The sometimes rule didn't work. Thank you to lagbox, the nullable rule worked!

Laravel 5.2 Validate File Array

I have a form with three fields: title, body and photo[]. I'm trying to validate it so that at least one item is filled in, but I can't seem to get it to work. If I upload a file I still receive an error for title and body.
public function rules()
{
return [
'title' => 'required_without_all:body,photo.*',
'body' => 'required_without_all:title,photo.*',
'photo.*' => 'required_without_all:title,body',
'photo.*' => 'mimes:jpeg,gif,png',
];
}
Update: Jonathan pointed out that I had my rules wrong. I've fixed them and am now using this. It's still not working; when I try to upload a photo I get the error message that the other fields are required.
public function rules()
{
return [
'title' => 'required_without:body,photo.*',
'body' => 'required_without:title,photo.*',
'photo.*' => 'required_without:title,body|mimes:jpeg,gif,png',
];
}
If you're looking to ensure the photo field is an array then you need 'photo' => 'array' and then you can use 'photo.*' => '' for the other validations of the array's children.
The rules are separated by a pipe character | so if you were going to combine the two in your example it would be 'photo.*' => 'required_without_all:title,body|mimes:jpeg,gif,png',. I don't see you using the pipe to separate rules so I can't be sure you are aware of it.
This may have been where you were going wrong in the first place (two keys in the associative array that are identical) and some kind of precedence taking affect negating one of the rules.
You could try something like this (for the record I think you were on the right track to begin with using required_without_all as this stipulates the need to be required if all of the given fields are missing):
public function rules()
{
return [
'title' => 'required_without_all:body,photo',
'body' => 'required_without_all:title,photo',
'photo' => 'array',
'photo.*' => 'required_without_all:title,body|mimes:jpeg,gif,png',
];
}
Reference

Do custom error messages in Laravel 4.2

I'm new in Larvel 4.2 here! How do I do a custom error messages in Laravel 4.2? And where do I put these codes? I've been using the defaults and I kind of wanted to use my own.
Did you try something? http://laravel.com/docs/4.2/validation#custom-error-messages
Did you use Google? Check the documentation (official) it has everything. Be less lazy.
$messages = array(
'required' => 'The :attribute field is required.',
);
$validator = Validator::make($input, $rules, $messages);
To add to the answer given by slick, here is how you could use it in a real example of a store function inside a controller:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'id1' => 'required|between:60,512',
'id2' => 'required|between:60,512',
'id3' => 'required|unique:table',
], [
'id1.required' => 'The first field is empty!',
'id2.required' => 'The second field is empty!',
'id3.required' => 'The third field is empty!',
'id1.between' => 'The first field must be between :min - :max characters long.',
'id2.between' => 'The second answer must be between :min - :max characters long.',
'id3.unique' => 'The third field must be unique in the table.',
]);
if ($validator->fails()) {
return Redirect::back()
->withErrors($validator)
->withInput();
}
//... Do something like store the data entered in to the form
}
Where the id should be the ID of the field in the form you want to validate.
You can check out all the rules you can use here.

Resources