Laravel validate request parameter only if it's availale - php

I implement laravel API, for validation I created a separate request file, and I write my validation rules in that and it's working fine. But the issue is I want to validate my request parameter only if it's available in request. Here is my code for that.
UserFormRequest.php
public function rules() {
return [
'customer_phone' => 'regex:/^([0-9\s\-\+\(\)]*)$/|max:15',
'customer_email' => 'required|email',
]
}

You can use the conditional validation using sometimes:
public function rules() {
return [
'customer_phone' => 'regex:/^([0-9\s\-\+\(\)]*)$/|max:15',
'customer_email' => 'sometimes|required|email',
]
}
In the example above, the customer_email field will only be validated if it is present.

Related

Laravel 5.2 validation fails when parameters value missing or equal symbol missing

Have a request
/web/v1/documents/?date=2019-05-22&sort=category
contrtoller:
$sort = $request->get('sort', 'commodity');
This value is optional and here validation:
DocumentsReportRequest:
public function rules()
{
return [
'sort' => ['in:commodity,category'],
];
}
if request
/web/v1/documents/?date=2019-05-22&sort
or
/web/v1/documents/?date=2019-05-22&sort=
Validation rule does not work and i got error.
Is there a way to validate parameters in this case?
You can add nullable or sometimes rule to your validation, like this:
public function rules()
{
return [
'sort' => ['nullable', 'in:commodity,category'],
];
}
Or present which requires the key to exist in the request but it can be empty.
You can use nullable validation if the parameter is not always available
public function rules()
{
return [
'sort' => ['nullable','in:commodity,category'],
];
}

only get validated data from laravel validator

When validating data with the validator, it's possible to get all processed data from the validator using the getData() method. However, that returns all data that has been passed into the validator. I only want the data that actually fit the validation pattern.
For example:
$data = [
'email' => email#example.com,
'unnecessaryKey' => 'whatever'
];
$validator = Validator::make($data, [
'email' => 'required|string',
]);
$validator->getData()
Would return the "unnecessaryKey" as well as the email. The question is: Is it possible to only return the email in this case, even though i passed in unnecessaryKey as well?
if you are getting the data from the $request you can try
$validator = Validator::make($request->only('email') , [
'email' => 'required|string',
]);
if you are validating a $data array then you can try
$validator = Validator::make(collect($data)->only('email')->toArray() , [
'email' => 'required|string',
]);
Hope this helps.
You should use Form Requests for this.
1) Create a Form Request Class
php artisan make:request StoreBlogPost
2) Add Rules to the Class, created at the app/Http/Requestsdirectory.
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
3) Retrieve the request in your controller, it's already validated.
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}

How to display custom vaildation error messages for API requests?

try{
$request->validate([
'aadhar' => 'required|digits:12|numeric',
'name' => 'required|string|max:511',
'dob' => 'required|date_format:Y-m-d',
'email' => 'required|email|max:255',
'address' => 'required|string',
'insuranceid' => 'required|digits_between:1,15|integer',
'password' => 'required|min:59|max:60',
]);
}
catch(Exception $error){
$message = $error->getMessage();
$status_code=400;
return response()->json(["message" => $message,"status_code" => $status_code]);
}
This is my piece of code for the validation of the request parameters sent to an API. The documentation gives details only about custom error messages in case of a form request.
The validation errors give the default message "The given data was invalid" but I would like to know which of the parameter was invalid. How do I give custom validation error messages for API requests validation?
First of all, to decouple your code, you could use a Form Request class. From the docs:
For more complex validation scenarios, you may wish to create a "form
request". Form requests are custom request classes that contain
validation logic.
This class contains two methods:
1 - rules, the place where you specify your rules, it should return an array of rules.
2 - authorize that return a boolean,this method control who is allowed to perform this request. By default is set to false, so every call will be rejected.
So, in your case, it should be something like this:
First, create your custom Request class executing this artisan command in your console:
php artisan make:request CreateCustomObjectRequest
This wil create a new class under app/Http/Requests:
class CreateCustomObjectRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// Implement here your Auth validation, something like:
return auth()->check();
// or just return "true" if you want to take care of this anywhere else.
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'aadhar' => 'required|digits:12|numeric',
'name' => 'required|string|max:511',
'dob' => 'required|date_format:Y-m-d',
'email' => 'required|email|max:255',
'address' => 'required|string',
'insuranceid' => 'required|digits_between:1,15|integer',
'password' => 'required|min:59|max:60',
];
}
}
And then, in your controller, instead of inject a regular Request object, we are gonna use this custom Request object:
use App\Http\Requests\CreateCustomObjectRequest;
// ...
public function store(CreateCustomObjectRequest $request)
{
// the rest of your controller logic.
}
Now, the part you are really interested in. To return errors in a json way you should add the next header when making a request:
Accept: Application/json
This header will tell Laravel that the output should be a json response, so it will convert it to json. Note that this will only work with the validation rules and when returning objects like return $someObject. To more further customization you shoud use something like:
return response()->json(['data' => $someObject], 200);
$validator = Validator::make($request->all(), [
'password' => [
'required',
'confirmed',
'between:8,55'
]
]);
if ( $validator->fails() ) {
return response()->json( [ 'errors' => $validator->errors() ], 400 );
}

Hooks in Laravel 5?

I'm creating a package and want hook functionality (the package should inject some extra validation rules when a user updates a field in my app).
I managed to do this using the event system. What I do is pass the $rules variable and $request into the listener, I modify the $rules variable and return it.
Would this be bad practice? What would be the recommended way of doing it?
I mean, it works. I'm just unsure if this is the best way to go about it.
Code below:
SettingsController.php (this is under App/ and where I'm validating on update)
public function update(Setting $setting, Request $request)
{
$rules = [
'package' => 'required|in:'.implode(config('app.packages'),','),
'name' => 'required|max:255|alpha_dash|not_contains:-|unique:auth_setting,name,'.$setting->id.',id,package,'.$setting->package,
'description' => '',
];
// Is this bad??
$rules = Event::fire(new SettingsWereSubmitted($request,$rules))[0];
$v = Validator::make($request->all(),$rules);
Then in my package (packages/exchange/src/Listeners) I got this listener (ValidateSettings.php):
public function handle(SettingsWereSubmitted $event)
{
if($event->request->package == 'exchange')
{
// Add rules
$rules = [
'fee' => 'required|decimal|min_amount:0|max_amount:1|max_decimal:8',
'freeze_trade' => 'required|in:1,0',
];
$event->rules['value'] = $rules[$event->request->name];
return $event->rules;
}
}
I'm looking at this piece of your code
if($event->request->package == 'exchange')
and think that you can achieve the same behaviour easier by using required_if validation rule.
$rules = [
'package' => 'required|in:'.implode(config('app.packages'),','),
'name' => 'required|max:255|alpha_dash|not_contains:-|unique:auth_setting,name,'.$setting->id.',id,package,'.$setting->package,
'description' => '',
'fee' => 'required_if:package,exchange|decimal|min_amount:0|max_amount:1|max_decimal:8',
'freeze_trade' => 'required_if:package,exchange|in:1,0',
];
ADDED:
By the way, I would suggest using Request classes to validate income requests and remove validation code from controllers because validation of request is responsibility of Request but not Controller.
It's pretty easy in Laravel. First, you create your request class in your Http\Requests folder:
class UpdateSomethingRequest extends Requst
{
public function rules()
{
return [
'package' => 'required|in:'.implode(config('app.packages'),','),
'name' => 'required|max:255|alpha_dash|not_contains:-|unique:auth_setting,name,'.$setting->id.',id,package,'.$setting->package,
'description' => '',
'fee' => 'required_if:package,exchange|decimal|min_amount:0|max_amount:1|max_decimal:8',
'freeze_trade' => 'required_if:package,exchange|in:1,0',
];
}
}
And then just remove that code from you Controller and type-hint new request class to update method like following:
public function update(Setting $setting, UpdateSomethingRequest $request)
{
// Your request is already validated here so no need to do validation again
}

Can I appy same rule for group of fields in Laravel5 request validation?

I am using laravel request form validation and I want to apply same rule for more than one field.Is it possible for in any simple way? or need to write code for individually.
My validation rule given below.
protected $rules = [
'phone' => ['max:11'],
'work_phone' => ['max:11'],
'mobile' => ['max:11'],
];
Can I group these filed in to single rule?
You can do some things inside the rules() method:
public function rules(){
$phoneRules = ['max:11'];
return [
'phone' => $phoneRules,
'work_phone' => $phoneRules,
'mobile' => $phoneRules
]
}
Or:
public function rules(){
$fields = ['phone', 'work_phone', 'mobile'];
return array_fill_keys($fields, ['max:11']);
}
In case you have other attributes to validate with other rules you'd need something like this:
public function rules(){
$fields = ['phone', 'work_phone', 'mobile'];
$phoneRules = array_fill_keys($fields, ['max:11']);
$otherRules = [
'foo' => 'required',
'bar' => 'min:30'
]
return array_merge($phoneRules, $otherRules);
}
You should refer to the Custom Validation Rules section of the documentation, which precisely address this problem : http://laravel.com/docs/5.0/validation#custom-validation-rules

Categories