Laravel validation - required only when two conditions are true - php

I want purchaser_first_name and purchaser_last_name to be required only when the value of gift input in the request is true and the value of authenticated input is false.
What I have tried so far:
public function rules()
{
return [
'gift' => 'required',
'authenticated'=>required,
'purchaser_first_name' => 'required_if:gift,true,required_if:authenticated,false',
'purchaser_last_name' => 'required_if:gift,true,required_if:authenticated,false',
];
}
This approach turns out to use OR operator instead I want the AND operator.

You can try like this:
'purchaser_first_name' => Rule::requiredIf(function () use ($request) {
return $request->input('gift') && !$request->input('authenticated');
}),
In the function, you can set your logic. I'm not sure what you need for real, but it's good for a start.
Also, check docs for more info about that.

Try to change your validation code as below :
return [
'gift' => 'required',
'authenticated'=>'required',
'purchaser_first_name' => 'required_if:gift,true|required_if:authenticated,false',
'purchaser_last_name' => 'required_if:gift,true|required_if:authenticated,false',
];

Related

PHP Validation for character ZERO"0"

I'm using a validator to validate user input in my Laravel 8.5x project.
This is the code I use:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(['SelectedMonth' => $SelectedMonth, 'SelectedStartDate' => $SelectedStartDate, 'SelectedEndDate' => $SelectedEndDate], [
'SelectedMonth' => 'required|max:7|regex:[^(\d{4}-)?\d{2}$]',
'SelectedStartDate' => 'nullable|max:12|regex:/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/',
'SelectedEndDate' => 'nullable|max:12|regex:/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/'
]);
if ($validator->fails()) {
abort(404);
} else {}
It works great but the problem is when the user doesn't set SelectedEndDate or SelectedStartDate to anything and the value stays "0" <- ZERO. The validator doesn't take "0" as nullable so it's always false. How can I add an exception for "0" to be true?
Thanks

Is there a way to set a validation on multiple inputs with similar name? Laravel 5.6

Is there a way to set a validation on multiple inputs with similar name? For ex -
public function rules()
{
return [
'zone1' => 'required|numeric',
'zone2' => 'required|numeric',
'zone3' => 'required|numeric',
];
}
Can I do something like 'zone*' => 'required|numeric'
You can use an asterisk as a wildcard but it may not be a great idea. With a rule like 'zone*' => 'required|numeric' as long as there's a single value that matches the condition the request will pass validation. For example, if a request has a valid value for zone2 but zone1 and zone3 are missing or non-numeric the validation will still pass

Add a validation which is not related to the form

I want to add a validation on a form. My actual form works, here it is:
public function store(Request $request, $id)
{
$this->validate($request, [
'subject' => 'required',
'body' => 'required',
]);
// Do something if everything is OK.
}
Now, I want to check if the user is "active" too. So something like:
\Auth::user()->isActive();
And return an error with the other validation errors if the user is not active.
Can I append something to the validator that has no relation with the form itself? I mean I want to add an error to the other errors if the user is not active.
That code is only validating the request variable (first argument of validate() function). So you will have to put someting in the request to validate it. It applies the rules to the object/array given.
$request->is_active = Auth::user()->isActive();
$this->validate($request, [
'subject' => 'required',
'body' => 'required',
'is_active' => true //or whatever rule you want
]);
Anyways, I never tried that so not sure it will work. The usual way is to do an if
if ( !Auth::user()->isActive() ) {
return redirect->back()->withErrors(['account' => 'Your account is not active, please activate it']);
}
//continue here

Laravel 5.2 validator: Validate Array request parameter, at least one value must be selected

I am having a form where i am having title, body, answers[][answer] and options[][option].
I want atleast one answer must be selected for the given question, for example:
i have ABC question and having 5 options for that question,now atleast one answer must be checked or all for given question.
Efforts
protected $rules = [
'title' => 'required|unique:contents|max:255',
'body' => 'required|min:10',
'type' => 'required',
'belongsto' => 'sometimes|required',
'options.*.option' => 'required|max:100',
'answers.*.answer' => 'required',
];
But this is not working. i want atleast one answer must be selected.
Please help me.
The problem is that on $_POST an array filled with empty strings will be passed if no answer is selected.
$answers[0][0] = ''
$answers[0][1] = ''
$answers[0][2] = ''
Hence the following will not work since array count will be greater than zero due to the empty strings:
$validator = Validator::make($request->all(), [
'answers.*' => 'required'
]);
The easiest way to solve this is to create a custom Validator rule by using Laravel's Validator::extend function.
Validator::extendImplicit('arrayRequireMin', function($attribute, $values, $parameters)
{
$countFilled = count(array_filter($values));
return ($countFilled >= $parameters[0]);
});
And then call it in your Validation request:
$validator = Validator::make($request->all(), [
'answers.*' => 'arrayRequireMin:1'
]);
The magic happens in array_filter() which removes all empty attributes from the array. Now you can set any minimum number of answers required.
Validator::extendImplicit() vs Validator::extend()
For a rule to run even when an attribute is empty, the rule must imply that the attribute is required. To create such an "implicit" extension, use the Validator::extendImplicit() method:
Laravel's validation docs
Try this,
'answer.0' => 'required'
it will help you. I think.

Laravel 4: Validate start and end date with before and after validation

I want to validate two date fields in a form which is from_date and end_date. Need to check from_date is less than end_date.
$rules = array('from_date' => array('sometimes','date_format:"Y-m-d"', 'before:'.Input::get('to_date') ),
'to_date' => array('sometimes','date_format:"Y-m-d"', 'after:'.Input::get('from_date') ) );
This is what i tried. But that does not work. If i give the to_date as empty value it will through the error.
I know that it is a question about Laravel 4 BUT if you are using Laravel 5.3 now you can use something like:
$rules = array(
'date_start' => 'required|date_format:Y-m-d|before_or_equal:date_end',
'date_end' => 'required|date_format:Y-m-d|after_or_equal:date_start'
);
$validator = Validator::make($request->all(), $rules);
Please use the below code in laravel 5.2 and it works fine for validating start and end date.
$this->validate($request, [
'start_date' => 'required|before:end_date',
'end_date' => 'required',
]);
Laravel 5:
Here is more extensive approach that follows modern principles and is more Laravel-like. This is a little more complex but still easy to follow and the end results is much cleaner.
Let's start by changing a few things. Let's reduce this to the specific problem, use newer array syntax and apply formatting.
$rules = [
'from_date' => [
'before:'.Input::get('to_date') // This is what we will learn to do
],
'to_date' => [
'after:'.Input::get('from_date') // Do this one on your own
]
];
Now let's create a new Request with php artisan make:request StoreWhateverRequest. This will create the App/HTTP/Request/StoreWhateverRequest.php file. Open that and place your rules in the return array of the rules() function.
return [
'from_date' => 'date',
'to_date' => 'date|after_field:from_date'
];
This will not work yet because after_field isn't available to use yet. Let's create that. We need a new class that extends validator. You can place it in app/Services. We need something similar to:
<?php namespace App\Services;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
class AfterFieldValidator extends Validator {
public function validateAfterField($attribute, $value, $parameters)
{
return Carbon::parse($value) > Carbon::parse($this->data[$parameters[0]]);
}
}
In the above we have: $attribute which is the name of the field we are checking (to_date), $value is the value of the field we are checking and $parameters is the parameters we passed to the Validator(from_date) seen in 'to_date' => 'date|afterField:from_date'. We also need the other data fields passed to the Validator, we can get these with $this->data. Then we just have to preform the logic appropriately. You really don't even need Carbon here but be sure to parse the string so we don't do string comparison.
Now we need to load this into the application. To do this put the below code inside the boot() function in app/Providers/AppServiceProviders.php.
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new afterFieldValidator($translator, $data, $rules, $messages);
});
The final step is easiest. Just inject and instance of StoreWhateverRequest into our Controller.
...
public function store(StoreWhateverRequest $request)
{
...
All done. I feel this is a pretty SOLID way to solve the problem.
Just came across this and thought I'd share an answer I found: Compare attributes in validation
Basically, you'd create a new Validator that extends Illuminate\Validation\Validator and write a custom rule in there:
public function validateEndAfter($attribute, $value, $parameters) {
$start_date = $this->getValue($parameters[0]); // get the value of the parameter (start_date)
return (strtotime($value) > strtotime($start_date));
}
then in your validator use the new rule:
$rules = [
'start_date' => 'required',
'end_date'=> 'required|end_after:start_date',
]
Anyhow,
I did as like this. So that even if any date in the form is empty that will auto fill and check the validation
$inputs = Input::all();
if(!empty($inputs))
{
$default_date_arr = array('from_date' => date('Y-m-d', strtotime('-1 days')), 'to_date' => date('Y-m-d'));
$inputs = $inputs+$default_date_arr;
}
$rules = array('from_date' => array('sometimes','date_format:"Y-m-d"', 'before:'.$to_date) ,
'to_date' => array('sometimes','date_format:"Y-m-d"', 'after:'.$from_date ) );
$validator = Validator::make($inputs,$rules);
if($validator->fails())
{ ... }
This may not be the answer for what i asked. But i needed just a way to finish this. May be will helpful for others.

Categories