How to Validate JSON Input using Requests? Laravel - laravel

I am sending some data with formData, and for one fields (object) I use: JSON.stringify(this.allValues).
and I try to validate all values from this.allValues .
Till now I tried 2 methods from here , now I try with the second one with "JsonApiMiddleware" .
But with this I validation(required) errors, even if the fields are not null.
public function rules()
{
$newValues = json_decode(request()->get('all_values')); // Here I have all values that needs to be validated
dd($newValues); // I post the respons for this below
$newValues = [
'saleforce_id' => 'required',
'customer_id' => 'required',
]
return $newValues;
}
""customer_id":49,"saleforce_id":"","lkp_invoicing_method_id":3,"lkp_product_category_id":10,"lkp_notice_period_id":5,"lkp_licence_term_id":9,"is_attrition_risk":false,"is_additional_users":false,"contract_value_exc_vat_annual":"257590...and many more

Treat the JSON object you send as a php associative array. For example let's say your sent data looks like this.
/* var allValues = */
{
data: {
requiredField1: value,
requiredField2: value,
requiredArrayField1: [
1,
2,
3,
],
optionalField1: value
}
}
Then, you can validate the data like this:
public function rules()
{
return: [
'data' => 'required|array',
'data.requiredField1' => 'required',
'data.requiredField2' => 'required',
'data.requiredArrayField1' => 'required|array',
'data.requiredArrayField1.*' => 'required|numeric',
'data.optionalField1' => 'nullable',
];
}

I found a solution.
I use the method from laracast, fureszpeter, method with middleware, and I edit it.
public function handle($request, Closure $next)
{
if ($request->has('all_values')) {
$request->merge([
'all_values' => json_decode($request->get('all_values'), true)
]);
} // only when I have all_values in my request
return $next($request);
}
}
In my existing Request:
public function rules()
{
$newValues = [
'all_values.saleforce_id' => 'required'
'all_values.customer_id' => 'required',
// and the rest of the files
]
return $newValues
}

Related

How to ignore unique value in updating laravel 8? [duplicate]

I know this question has been asked many times before but no one explains how to get the id when you're validating in the model.
'email' => 'unique:users,email_address,10'
My validation rule is in the model so how do I pass the ID of the record to the validation rule.
Here is my models/User
protected $rules_update = [
'email_address' => 'required|email|unique:users,email_address,'.$id,
'first_name' => "required",
'last_name' => "required",
'password' => "required|min:6|same:password_confirm",
'password_confirm' => "required:min:6|same:password",
'password_current' => "required:min:6"
];
models/BaseModel
protected $rules = array();
public $errors;
/*
* #data: array, Data to be validated
* #rules: string, rule name in model
*/
public function validate($data, $rules = "rules") {
$validation = Validator::make($data, $this->$rules);
if($validation->passes()) {
return true;
}
$this->errors = $validation->messages();
return false;
}
Just a side note, most answers to this question talk about email_address while in Laravel's inbuilt auth system, the email field name is just email. Here is an example how you can validate a unique field, i.e. an email on the update:
In a Form Request, you do like this:
public function rules()
{
return [
'email' => 'required|email|unique:users,email,'.$this->user->id,
];
}
Or if you are validating your data in a controller directly:
public function update(Request $request, User $user)
{
$request->validate([
'email' => 'required|email|unique:users,email,'.$user->id,
]);
}
Update:
If you are updating the signed in user and aren't injecting the User model into your route, you may encounter undefined property when accessing id on $this->user. In that case, use:
public function rules()
{
return [
'email' => 'required|email|unique:users,email,'.$this->user()->id,
];
}
A more elegant way since Laravel 5.7 is:
public function rules()
{
return [
'email' => ['required', 'email', \Illuminate\Validation\Rule::unique('users')->ignore($this->user()->id)]
];
}
P.S: I have added some other rules, i.e. required and email, in order to make this example clear for newbies.
One simple solution.
In your Model
protected $rules = [
'email_address' => 'sometimes|required|email|unique:users',
..
];
In your Controller, action:update
...
$rules = User::$rules;
$rules['email_address'] = $rules['email_address'] . ',id,' . $id;
$validationCertificate = Validator::make($input, $rules);
There is an elegant way to do this. If you are using Resource Controllers, your link to edit your record will look like this:
/users/{user}/edit OR /users/1/edit
And in your UserRequest, the rule should be like this :
public function rules()
{
return [
'name' => [
'required',
'unique:users,name,' . $this->user
],
];
}
Or if your link to edit your record look like this:
/users/edit/1
You can try this also:
public function rules()
{
return [
'name' => [
'required',
'unique:users,name,' . $this->id
],
];
}
From Laravel 5.7, this works great
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Forcing A Unique Rule To Ignore A Given ID:
Test below code:
'email' => 'required|email|unique:users,email_address,'. $id .'ID'
Where ID is the primary id of the table
If i understand what you want:
'email' => 'required|email|unique:users,email_address,'. $id .''
In model update method, for exemple, should receive the $id with parameter.
Sorry my bad english.
Here is the solution:
For Update:
public function controllerName(Request $request, $id)
{
$this->validate($request, [
"form_field_name" => 'required|unique:db_table_name,db_table_column_name,'.$id
]);
// the rest code
}
That's it. Happy Coding :)
The Best Option is here try just once no need more code when unique validation on updating data
'email' => 'unique:users,email_address,' . $userId,
hereemailis field name and users is table name and email_address is table attribute name which you want unique and $userid is updating row id
public function rules()
{
switch($this->method())
{
case 'GET':
case 'DELETE':
{
return [];
}
case 'POST':
{
return [
'name' => 'required|unique:permissions|max:255',
'display_name' => 'required',
];
}
case 'PUT':
case 'PATCH':
{
return [
'name' => 'unique:permissions,name,'.$this->get('id').'|max:255',
'display_name' => 'required',
];
}
default:break;
}
}
an even simpler solution tested with version 5.2
in your model
// validator rules
public static $rules = array(
...
'email_address' => 'email|required|unique:users,id'
);
You can try this.
protected $rules_update = [
'email_address' => 'required|email|unique:users,email_address,'. $this->id,
'first_name' => "required",
'last_name' => "required",
'password' => "required|min:6|same:password_confirm",
'password_confirm' => "required:min:6|same:password",
'password_current' => "required:min:6"
];
In Laravel 8.x you can use Rule::unique method as well
Forcing A Unique Rule To Ignore A Given ID:
use Illuminate\Validation\Rule;
public function update(Request $request, Post $post)
{
$validatedData = $request->validate([
'name' => ['required', 'max:60', Rule::unique('posts')->ignore($post->id)],
]);
$post->update($validatedData);
return redirect(route('posts.index'))->with('status', 'post updated successfully');
}
Do One step in controller
Works Fine with Laravel 9
$request->validate([
'name'=>'required|unique:categories,name,'.$id,
]);
If you have a separate rules method. You can use easier the following syntax.
public function rules()
{
return [
'email' => "required|unique:users,email,{$this->id}"
];
}
$rules = [
"email" => "email|unique:users, email, '.$id.', user_id"
];
In Illuminate\Validation\Rules\Unique;
Unique validation will parse string validation to Rule object
Unique validation has pattern: unique:%s,%s,%s,%s,%s'
Corresponding with: table name, column, ignore, id column, format wheres
/**
* Convert the rule to a validation string.
*
* #return string
*/
public function __toString()
{
return rtrim(sprintf('unique:%s,%s,%s,%s,%s',
$this->table,
$this->column,
$this->ignore ?: 'NULL',
$this->idColumn,
$this->formatWheres()
), ',');
}
There is a simple and elegant way to do this. If you are passing the user_id in a body request or through a query parameter.
e.g
/update/profile?user_id=
Then in your request rules
public function rules(Request $request)
{
return [
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => ['required','email', 'string', Rule::unique('users')->ignore($request->user_id )],
'phone_number' => ['required', 'string', Rule::unique('users')->ignore($request->user_id )],
];
}
Better Still, you can pass in auth->id() in place of $request->user_id to get the login user id.
Found the easiest way, working fine while I am using Laravel 5.2
public function rules()
{
switch ($this->method()) {
case 'PUT':
$rules = [
'name' => 'required|min:3',
'gender' => 'required',
'email' => 'required|email|unique:users,id,:id',
'password' => 'required|min:5',
'password_confirmation' => 'required|min:5|same:password',
];
break;
default:
$rules = [
'name' => 'required|min:3',
'gender' => 'required',
'email' => 'required|email|unique:users',
'password' => 'required|min:5',
'password_confirmation' => 'required|min:5|same:password',
];
break;
}
return $rules;
}
i would solve that by doing something like this
public function rules()
{
return [
'name' =>
'required|min:2|max:255|unique:courses,name,'.\Request::get('id'),
];
}
Where you get the id from the request and pass it on the rule
You can also use model classpath, if you don't want to hard code the table name.
function rules(){
return [
'email' => ['required','string',
Rule::unique(User::class,'email')->ignore($this->id)]
];
}
Here $this->id is either 0 or the record Id to be updated.
Use for Laravel 6.0
use Illuminate\Validation\Rule;
public function update(Request $request, $id)
{
// Form validation
$request->validate([
'category_name' => [
'required',
'max:255',
Rule::unique('categories')->ignore($id),
]
]);
}
After researching a lot on this laravel validation topic including unique column, finally got the best approach. Please have a look
In your controller
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class UserController extends Controller
{
public function saveUser(Request $request){
$validator = Validator::make($request->all(),User::rules($request->get('id')),User::$messages);
if($validator->fails()){
return redirect()->back()->withErrors($validator)->withInput();
}
}
}
saveUser method can be called for add/update user record.
In you model
class User extends Model
{
public static function rules($id = null)
{
return [
'email_address' => 'required|email|unique:users,email_address,'.$id,
'first_name' => "required",
'last_name' => "required",
'password' => "required|min:6|same:password_confirm",
'password_confirm' => "required:min:6|same:password",
'password_current' => "required:min:6"
];
}
public static $messages = [
'email_address.required' => 'Please enter email!',
'email_address.email' => 'Invalid email!',
'email_address.unique' => 'Email already exist!',
...
];
}
This is what I ended up doing. I'm sure there is a more efficient way of doing this but this is what i came up with.
Model/User.php
protected $rules = [
'email_address' => 'sometimes|required|email|unique:users,email_address, {{$id}}',
];
Model/BaseModel.php
public function validate($data, $id = null) {
$rules = $this->$rules_string;
//let's loop through and explode the validation rules
foreach($rules as $keys => $value) {
$validations = explode('|', $value);
foreach($validations as $key=>$value) {
// Seearch for {{$id}} and replace it with $id
$validations[$key] = str_replace('{{$id}}', $id, $value);
}
//Let's create the pipe seperator
$implode = implode("|", $validations);
$rules[$keys] = $implode;
}
....
}
I pass the $user_id to the validation in the controller
Controller/UserController.php
public function update($id) {
.....
$user = User::find($user_id);
if($user->validate($formRequest, $user_id)) {
//validation succcess
}
....
}
While updating any Existing Data Write validator as following:
'email' => ['required','email', Rule::unique('users')->ignore($user->id)]
This will skip/ignore existing user's id's unique value matching for the specific column.
Test below code:
$validator = Validator::make(
array(
'E-mail'=>$request['email'],
),
array(
'E-mail' => 'required|email|unique:users,email,'.$request['id'],
));
Since you will want to ignore the record you are updating when performing an update, you will want to use ignore as mentioned by some others. But I prefer to receive an instance of the User rather then just an ID. This method will also allow you to do the same for other models
Controller
public function update(UserRequest $request, User $user)
{
$user->update($request->all());
return back();
}
UserRequest
public function rules()
{
return [
'email' => [
'required',
\Illuminate\Validation\Rule::unique('users')->ignoreModel($this->route('user')),
],
];
}
update: use ignoreModel in stead of ignore
Very easy to do it ,
Write it at your controller
$this->validate($request,[
'email'=>['required',Rule::unique('yourTableName')->ignore($request->id)]
]);
Note : Rule::unique('yourTableName')->ignore($idParameter) , here $idParameter you can receive from get url also you can get it from hidden field.
Most important is don't forget to import Rule at the top.
If a login user want to update the email then auth() helper function will give us the login user id auth()->user()->id
Laravel helpers#method-auth
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore(auth()->user()->id),
],
]);
if Admin want to change the specific user information from User list then validation will be like this :
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($request->user),
],
Laravel validation#rule-unique
$request object contain the current route related model objects. Which gives the model.
Try dd($request)
Most answers to this question refer to email_address, but in Laravel's inbuilt authentication system, the email field name is just email. Here is an example of validating a unique field, i.e. an email on the update:
Form Requests look like this:
public function rules()
{
return [
'email' => [ 'required','email', Rule::unique('users')->ignore($this->id ?? 0)]];
}
?? 0 If you use this then if hare id does not exist this request will not give you an error
Save
Whenever you access the id property of $this->user, you may encounter an undefined property if you haven't injected the User model into your route. If that is the case, use:
public function rules()
{
return [
'email' => 'required|email|unique:users,email,'.$this->user()->id ?? 0,
];
}
?? 0 If you use this then if hare id does not exist this request will not give you an error
My solution:
$rules = $user->isDirty('email') ? \User::$rules : array_except(\User::$rules, 'email');
Then in validation:
$validator = \Validator::make(\Input::all(), $rules, \User::$messages);
The logic is if the email address in the form is different, we need to validated it, if the email hasn't changed, we don't need to validate, so remove that rule from validation.
For unique rule in the controller - which obviously will be different for the store method and the update method, I usually make a function within the controller for rules which will return an array of rules.
protected function rules($request)
{
$commonRules = [
'first_name' => "required",
'last_name' => "required",
'password' => "required|min:6|same:password_confirm",
'password_confirm' => "required:min:6|same:password",
'password_current' => "required:min:6"
];
$uniqueRules = $request->id
//update
? ['email_address' => ['required', 'email', 'unique:users,email' . $request->get('id')]]
//store
: ['email_address' => ['required', 'email', 'unique:users,email']];
return array_merge($commonRules, $uinqueRules);
}
Then in the respective store and update methods
$validatedData = $request->validate($this->rules($request));
This saves from defining two different rule sets for store and update methods.
If you can afford to compromise a bit on readability, it can also be
protected function rules($request)
{
return [
'first_name' => "required",
'last_name' => "required",
'password' => "required|min:6|same:password_confirm",
'password_confirm' => "required:min:6|same:password",
'password_current' => "required:min:6",
'email_address' => ['required', 'email', 'unique:users,email' . $request->id ?: null]
];
}

How to use same Laravel Resource for different API response

i want to make two different functions on resource so that i can get a two different response .i.e i want the resource to return data without image and with image.
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'area_code' => $this->area_code
];
}
public function toArrayWithImages($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'area_code' => $this->area_code,
'image' => $this->image
];
}
this is what i tried but dont know how to point to the second function 'toArrayWithImages' . can someone explain me this ?
This is my controller ..
public function getAllBusinessAreas()
{
try {
$areas = Area::orderBy('id', 'desc')->get();
return BusinessAreaResource::collection($areas);
} catch (Exception $e) {
return sendErrorResponse('Error fetching Business Areas', true, 500);
}
}
what it does is by default it hits the toArray function i want to be specific which function to hit from controller. is it possible to do it ?
So basically what i am doing is adding an additional parameter to your request, you can use a flash session variable as well if it is not possible to attach extra params to your request, to filter weather it goes to the function which returns image or data without image.
public function toArray($request)
{
if($request->with_image)
{
this::toArrayWithImages($request->except('with_image'));
}
else
{
this::toArrayWithoutImages($request->except('with_image'));
}
}
public function toArrayWithoutImages($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'area_code' => $this->area_code
];
}
public function toArrayWithImages($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'area_code' => $this->area_code,
'image' => $this->image
];
}

How to adopt FormRequest to API JSON request?

How to adopt FormRequest to API JSON request? Now it looks as:
class CreateOrder extends FormRequest
{
// Validation rules
public function rules()
{
return [
'DeliveryDate' => 'required|date_format:d-m-Y H:m:s',
'PostCard' => 'boolean',
'PostCardText' => 'string|max:250',
'PhotoBefore' => 'boolean',
'Remark' => 'string|max:200',
'OrderDate' => 'required|date_format:d-m-Y',
'CallRecipientBefore' => 'boolean',
'AnonymousDelivery' => 'boolean',
'PhotoAfter' => 'boolean',
'Employers_Id' => 'required|integer',
'Employers_Id' => 'required|integer',
'Partners_Id' => 'required|integer',
];
}
public function authorize()
{
return true;
}
}
And using:
public function store(CreateOrder $request)
{
dd(Request::get('DeliveryDate'));
dd($request->all()); // Or
}
When I send data to this endpoint, Laravel instead showing incoming data $request, does redirect.
Sending data
Using Postman data is sent in raw format as:
{
"DeliveryDate": "2018-01-01"
}
As result I give Laravel screen saver.
So, I have did some tests, method is not called at all:
public function store(CreateOrder $request)
{
dd('ss');
}
Seems an error in class: CreateOrder

Laravel 5 Form request, require input on create, but optional on edit

I am using laravel 5.6 resources controllers and form request the problem is that i have some inputs that are required on created, but on edit are optionals like file inputs. So i have this form request
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProgramRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
'name.*' => 'required',
'description.*' => 'required',
'logo' => 'required|image|max:3000',
'logo_alt' => 'required|image|max:3000'
];
}
}
the fields logo and logo_alt must be sent when creating the program, but when editing it sending a logo is optional.
is there a way to validate both cases with the same form request or i have to create a different form request for editing and for creating?
You can use $this->method() to check which request method has been used and show different rules for each case:
public function rules()
{
switch($this->method())
{
case 'GET':
case 'DELETE':
{
return [];
}
case 'POST':
{
return [
'name.*' => 'required',
'description.*' => 'required',
'logo' => 'required|image|max:3000',
'logo_alt' => 'required|image|max:3000'
];
}
case 'PUT':
{
return [
'description.*' => 'required',
'logo' => 'nullable|image|max:3000',
'logo_alt' => 'nullable|image|max:3000'
];
}
case 'PATCH':
{
return [];
}
default:break;
}
}
In this above example the POST will be for your create and the PUT will be for your update.
Notice I've used nullable for the PUT validation rules, this tells the request object that the field is optional.
Instead of:
return [
//
'name.*' => 'required',
'description.*' => 'required',
'logo' => 'required|image|max:3000',
'logo_alt' => 'required|image|max:3000'
];
you can use:
$rules = [
'name.*' => 'required',
'description.*' => 'required',
'logo' => ['image', 'max:3000'],
'logo_alt' => ['image', 'max:3000'],
];
if ($this->isMethod('POST')
{
$rules['logo'][] = 'required';
$rules['logo_alt'][] = 'required';
}
return $rules;
So basically you have rules for update but in addition for POST method you make logo and logo_alt required. You could use pipe syntax | too, but it's more convenient to use array syntax for rules so you can later do such things when needed.
I know I'm late. But I found some better solustion like this
$requiredOrNull = '';
switch ($this->method()) {
case 'POST':
$requiredOrNull = 'nullable';
break;
case 'PUT':
$requiredOrNull = 'required';
break;
}
return [
//
'name.*' => 'required',
'description.*' => 'required',
'logo' => $requiredOrNull . '|image|max:3000',
'logo_alt' => $requiredOrNull . '|image|max:3000'
];
}
Basically it check if the method is post, your logo and logo_alt would be required, but if the method is put, it would be nullable

Laravel Form Request Add Custom Variable After Validation

This is my form request code, i want to add new variable after validation success, so i can access that variable at my controller :
class CouponRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'start_year' => 'required',
'start_month' => 'required',
'start_day' => 'required',
'start_time' => 'required',
'finish_year' => 'required',
'finish_month' => 'required',
'finish_day' => 'required',
'finish_time' => 'required',
];
}
public function afterValidation()
{
$this->start_date = Carbon::create( $this->start_year, $this->start_month, $this->start_day );
}
}
So after validation has no error, i can call this instance at my controller :
$request->start_date;
Could i do this?
All above methods work but in my opinion I would override the passedValidation method in the form request class. This method is called after the validation checks are passed and hence keep the data clean.
Ex.
public function passedValidation()
{
$this->merge([
'start_date' => Carbon::create( $this->start_year, $this->start_month, $this->start_day )
]);
}
If you dump the data now you should see your new start_date value as well.
You could do this
public function afterValidation()
{
$this->request->add([
'start_date' => Carbon::create($this->start_year, $this->start_month, $this->start_day)
]);
}
public function validate()
{
parent::validate();
$this->afterValidation();
}
And then access the attribute in your controller as
$request->get('start_date');
In your form request use function prepareForValidation()
protected function prepareForValidation(): void
{
$this->merge([
'start_date' => Carbon::now()
]);
}
Cheers!
I am using this method after success request for manipulations.
Source: 50116187/1101038
public function withValidator(Validator $validator)
{
if ( $validator->fails() ) {
\Log::info('Error! No Manipulation!');
}else{
$this->merge([
'custom' => 'Test Manipulation!'
]);
\Log::info('Success Manipulation!');
}
}
I made the validation in the Controller. The method has a "Request $request" parameter. I have a I do this:
$input = $request->all();
$input['my_new_field] = 'the_data';

Resources