In my controller I have a store method that is validating the request data:
$request->validate([
'title' => 'required',
'description' => 'required',
'date' => [
'required',
new DateFormatRule
],
'closed' => 'nullable',
'time_start' => 'required_if:closed,0',
'time_end' => [
'required_if:closed,0',
new TimeDurationRule($request->time_start)
],
]);
closed is a boolean. If closed is false, the time_start and time_end fields are required. This seems to be working as expected.
However, if I submit a request with closed as true, I am getting caught in my custom TimeDurationRule:
'time_end' => [
'required_if:closed,0',
new TimeDurationRule($request->time_start)
],
How can I make new TimeDurationRule($request->time_start) conditional? For example, if closed is true, I am manually setting time_end to null so time_start/time_end do not need a value (not required).
If I comment my custom rule out, everything works as expected.
Thank you for any suggestions!
You can pass $request->closed to your TimeDurationRule and then in the passes method of the rule, you can do something like this:
class TimeDurationRule implements Rule
{
public $closed;
public function __construct(/*all needed parameters*/, $closed)
{
$this->closed = $closed;
}
public function passes($attribute, $value)
{
if(!$closed){
return true
}
// the rest of validation logic
}
}
And then
new TimeDurationRule(/*all needed parameters*/, $request->closed)
You can read more about it here as well: https://laracasts.com/discuss/channels/laravel/create-custom-validation-rule-with-additional-parameters-implement-in-request
Hope it helps!
Related
I have a problem with the form request validation rules. I need to check additional data when the input date is less than 18 years ago (the user is not an adult). I write rules but it doesn't work. This is my code:
$adultDate = Carbon::now()->subYears(18)->format('Y-m-d');
$rules = [
"brith_date" => 'required|date',
"patron_name" => "required_if:brith_date,after,".$adultDate."|string"
];
return $rules;
you can use Rule::when($condition, $rules)
<?php
use Illuminate\Validation\Rule;
public function rules()
{
$adultDate = Carbon::now()->subYears(18);
$condition=Carbon::parse($this->brith_date)->isAfter($adultDate);
return [
'brith_date' => ['required','date'],
'patron_name' => ['required' ,
Rule::when($condition, ['string']),
];
}
I've made a custom validator, that compares two dates, and I want to show a message to the user which says the one date (the invoicedate in my example) must be earlier than the other one (the deadline in my example).
Inside my custom validator I write:
public static validateInfo(Request $request)
{
$validator = Validator::make($request->all(), [
'referencenumber' => 'required|min:2|max:64',
'invoicedate' => 'required|date',
'deadline' => 'null|date'
]);
$validator->after(function ($validator) use ($request) { // custom static function where I compare two dates using strtotime(), if invoicedate and deadline are still valid, and return false or true
if (InvoiceValidator::invalidDeadline($validator, $request)) {
$validator->errors()->add('deadline', __('validation.negative_date_difference', [
'attribute1' => 'deadline',
'attribute2' => 'invoicedate'
]));
}
});
return $validator;
}
And inside resources\lang\en\validation.php I write:
<?php
return [
// ...
'negative_date_difference' => 'The :attribute1 may not be earlier than the :attribute2.',
// ...
'attributes' => [
'referencenumber' => 'Reference Number', // This works. It's fine
'invoicedate' => 'Invoice Date' // But this does not work, of course, because I wrote $validator->errors()->add('deadline'...); so the deadline is the only targetted attribute name here
],
]
Current output is:
The Deadline may not be earlier than the invoicedate.
My question: how to bypass invoicedate, when this is the message I want to see?
The Deadline may not be earlier than the Invoice Date.
Inside resources\lang\en\messages.php I've added a new message:
<?php
return [
'invoice_date' => 'Invoice Date'
]
Then edited my custom validation function, as follows:
if (InvoiceValidator::invalidDeadline($validator, $request)) {
$validator->errors()->add('deadline', __('validation.negative_date_difference', [
'attribute1' => 'deadline',
'attribute2' => __('messages.invoice_date') // This works
]));
}
Lets say I have the following Custom Request:
class PlanRequest extends FormRequest
{
// ...
public function rules()
{
return
[
'name' => 'required|string|min:3|max:191',
'monthly_fee' => 'required|numeric|min:0',
'transaction_fee' => 'required|numeric|min:0',
'processing_fee' => 'required|numeric|min:0|max:100',
'annual_fee' => 'required|numeric|min:0',
'setup_fee' => 'required|numeric|min:0',
'organization_id' => 'exists:organizations,id',
];
}
}
When I access it from the controller, if I do $request->all(), it gives me ALL the data, including extra garbage data that isn't meant to be passed.
public function store(PlanRequest $request)
{
dd($request->all());
// This returns
[
'name' => 'value',
'monthly_fee' => '1.23',
'transaction_fee' => '1.23',
'processing_fee' => '1.23',
'annual_fee' => '1.23',
'setup_fee' => '1.23',
'organization_id' => null,
'foo' => 'bar', // This is not supposed to show up
];
}
How do I get ONLY the validated data without manually doing $request->only('name','monthly_fee', etc...)?
$request->validated() will return only the validated data.
Example:
public function store(Request $request)
{
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
$validatedData = $request->validated();
}
Alternate Solution:
$request->validate([rules...]) returns the only validated data if the validation passes.
Example:
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
}
OK... After I spent the time to type this question out, I figured I'd check the laravel "API" documentation: https://laravel.com/api/5.5/Illuminate/Foundation/Http/FormRequest.html
Looks like I can use $request->validated(). Wish they would say this in the Validation documentation. It makes my controller actions look pretty slick:
public function store(PlanRequest $request)
{
return response()->json(['plan' => Plan::create($request->validated())]);
}
This may be an old thread and some people might have used the Validator class instead of using the validator() helper function for request.
To those who fell under the latter category, you can use the validated() function to retrieve the array of validated values from request.
$validator = Validator::make($req->all(), [
// VALIDATION RULES
], [
// VALIDATION MESSAGE
]);
dd($validator->validated());
This returns an array of all the values that passed the validation.
This only starts appearing in the docs since Laravel 5.6 but it might work up to Laravel 5.2
I try to validate a POST request.
The format is: d.m.Y (12.1.2017)
My rule is required|date_format:d.m.Y for this field.
I get this error message:
InvalidArgumentException in Carbon.php line 425:
Unexpected data found.
Unexpected data found.
Data missing
If I change the . to - or even / it is working -> POST data changed before to match the rule.
I need the German format for this.
edit:
My validation rules:
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'required|date_format:d.m.Y',
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
Wrap your Format should work i just tried with 5.2 it's working fine.
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'required|date_format:"d.m.Y"',
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
But the error what you added in question InvalidArgumentException in Carbon.php line 425: it seems something else my guess you are using expiration_date some where in controller or model like this with Carbon
echo Carbon::createFromFormat('Y-m-d', '12.1.2017');
You should try something like this
echo Carbon::parse('12.1.2017')->format('Y-m-d')
Wrap your format into quotes:
'date_format:"d.m.Y"'
Try like this,
public function rules()
{
return [
'title' => 'required|max:255',
'expiration_date' => 'date_format:"d.m.Y"|required', // I have changed order of validation
//'description' => 'required',
'provision_agent' => 'required|integer|between:0,100',
'discount_consumer' => 'required|integer|between:0,100',
'quota' => 'required|integer',
];
}
Hope this will solve your problem.
If you don't succeed solving the issue otherwise, you can still use a custom validation rule:
Validator::extend('date_dmY', function ($attribute, $value) {
$format = 'd.m.Y';
$date = DateTime::createFromFormat($format, $value);
return $date && $date->format($format) === $value;
}, 'optional error message');
The extra check $date->format($format) === $value is to avoid erroneously accepting out-of-range dates, e.g. "32.01.2017". See this comment on php.net.
Once the custom validation rule has been defined, you can use it like so:
public function rules() {
return [
'expiration_date' => 'required|date_dmY',
];
}
I am building a form in which user must be of age 18 years or above.I have tried some methods but didn't worked.
in my controller:
$this->validate($request,[
'birthday' => 'required|date|before:-18 years',
]);
in request.php:(searched over internet)
abstract class Request extends FormRequest
{
public function messages()
{
return [
'birthday.before' => 'You must be 18 years old or above',
];
}
}
Actually, I don't clearly about your question.
If you want custom message of before validate, please go to resources/lang/en/validation.php and change it at
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
Hope it help!
You can compute the age from the date, then validate it as a number.
or you can validate a date, which is 18 years before now
$dt = new Carbon\Carbon();
$before = $dt->subYears(18)->format('Y-m-d');
$rules = [
'dob' => 'required|date|before:' . $before
];
or you can extend the validate and make custom one like in this answer : Check user's age with laravel validation rules
Hi to get your validation errors store your validator inside a variable
then just use $validator->errors() to get its errors
$validator = Model::validate($request,[
'birthday' => 'required|date|before:-18 years',
]);
$errors = $validator->errors();
echo "You error in birthday: ".$errors->get('birthday')[0];