Laravel: Validation rules that depends on what the request is using condition - php

I just created a request using php artisan make:request MyExampleRequest and the next thing that I have to do is to have a logic where I can get the value from form input and compare it and choose which validation should the logic follow.
Inside the rules() method of MyExampleRequest.php, the logic would be like:
public function rules()
{
if($valueFromPostInput === '2') {
return [
'email' => 'required|email',
'confirm_email' => 'required|email|same:email',
'g-recaptcha-response' => 'required|recaptcha'
];
}
return [
'email' => 'required|email',
'g-recaptcha-response' => 'required|recaptcha'
];
}
I tried this logic:
public function rules()
{
if($this->attributes->has('valueFromPostInput') === '2') {
// more codes... }
}
But that didn't work.
I know I can achive this one using the logic below inside the MyExampleController.php Controller:
public function create(Request $request)
{
if($request->valueFromPostInput === '2') {
$this->validate($request, [
'email' => 'required|email',
'confirm_email' => 'required|email|same:email',
'g-recaptcha-response' => 'required|recaptcha'
]);
} else {
$this->validate($request, [
'email' => 'required|email',
'g-recaptcha-response' => 'required|recaptcha'
]);
}
}
But I want that to happen in Request that I've made using php artisan make:request MyExampleRequest and use that in my controller like public function(MyExampleRequest $request).
I searched for the answer I cannot find any. I'd really appreciated your response.
PS: English is not my native language.

You could use the request helper:
public function rules()
{
$baseRules = [
'email' => 'required|email',
'g-recaptcha-response' => 'required|recaptcha'
];
if(request()->get("valueFromPost") === '2') {
return $baseRules + [
'confirm_email' => 'required|email|same:email'
];
}
return $baseRules;
}
Or the shorter (but less readable) version:
public function rules()
{
return [
'email' => 'required|email',
'g-recaptcha-response' => 'required|recaptcha'
] + (request()->get("valueFromPost") === '2' ? [ 'confirm_email' => 'required|email|same:email' ] : []);
}

Related

How do you customize the default login error message in laravel 8

I was browsing through the web and looking for solution on how can I modify this error message on Jetstream login:
Inside app/Actions/Fortify there is a file CreateNewUser.php where I can put some validation custom message on each field like this:
public function create(array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'phone' => ['required', 'string', 'max:17'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
],[
'name.required'=>'Name is required',
'email.required'=>'Email is required',
'phone.required'=>'Phone is required',
])->validate();
However, there is none for Login.php. I search the web and saw something about vendors/laravel/fortify/src/Actions/AttemptToAuthenticate.php but its consist with lots of code where I don't know where to put the customization:
public function handle($request, $next)
{
if (Fortify::$authenticateUsingCallback) {
return $this->handleUsingCustomCallback($request, $next);
}
if ($this->guard->attempt(
$request->only(Fortify::username(), 'password'),
$request->filled('remember'))
) {
return $next($request);
}
$this->throwFailedAuthenticationException($request);
}
Is there an easy way to customize the "The email field is required" to a different custom message in Laravel 8?
Been stuck for a couple of hours.
You can customize FortifyServiceProvider inside App > Providers by using the Fortify::authenticateUsing method and it should be called from the boot method.
public function boot()
{
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
} else {
$request->session()->flash('message', 'Invalid!');
return false;
}
});
}
Reference
step 1 go to vendor\laravel\fortify\src\Http\Requests\LoginRequest.php
step 2 in the loginRequest.php you will find two method
public function authorize()
{
return true;
}
public function rules()
{
return [
Fortify::username() => 'required|string',
'password' => 'required|string',
];
}
step 3 add the following method below
public function messages() {
return = [
'email.required' => 'email required',
'password.required' => 'password required'
];
}

Laravel Complex Conditional Validation

I'm trying to create a validator that require at least one of three input.
I tried this
protected function validateFundingSource (): array
{
return request()->validate([
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'province' => Rule::requiredIf(!request('national')),
'url' => [
'required_without_all:phone,email',
'active_url'
],
'phone' => [
'required_without_all:url,email|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im'
],
'email' => [
'required_without_all:url,phone|email:rfc,dns'
],
'categories' => 'exists:categories,id'
]);
}
But it was was forcing only the first field (url). So I tried with Complex Conditional Validation.
protected function validateFundingSource ()
{
$v = Validator::make(request()->all(), [
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'categories' => 'exists:categories,id',
]);
$v->sometimes('province', 'required', function ($input) {
return ($input->national === null) ;
});
$v->sometimes('url', 'required|active_url', function ($input) {
return (($input->phone === null) && ($input->email === null));
});
$v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
return (($input->url === null) && ($input->email === null));
});
$v->sometimes('email', 'required|email:rfc,dns', function ($input) {
return (($input->url === null) && ($input->phone === null));
});
return $v;
}
But still no luck... Now it's never required I can submit all three empty field and it's working...
Any clues to help me please ?
Thank you !
You code is working fine. you just forget to check if validate pass or not.
because when you use Validator::make you need to manually check it. for request()->validate laravel will do it for you. inside your validateFundingSource () function just check it pass validate or not before return like this:
private function validateFundingSource () {
$v = Validator::make(request()->all(), [
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'categories' => 'exists:categories,id',
]);
$v->sometimes('province', 'required', function ($input) {
return ($input->national === null) ;
});
$v->sometimes('url', 'required|active_url', function ($input) {
return (($input->phone === null) && ($input->email === null));
});
$v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
return (($input->url === null) && ($input->email === null));
});
$v->sometimes('email', 'required|email:rfc,dns', function ($input) {
return (($input->url === null) && ($input->phone === null));
});
// check if validae failed
if($v->fails()) {
dd('fail', $v); // do something when it failed
}
}
also sorry for my bad English & hope it help
If you're looking for "at least one of" url, phone, or email then you want to use required_without. This rule means the field is required when any of the specified fields are missing; required_without_all means it's required when all of the specified fields are missing.
You are also confusing rule syntax, you must use either array or pipe-delimited string syntax, not both at once.
You may want to improve your phone number regex as well; + -. (000-111.9999 #8 is not a great phone number, but would pass your validation. I'd suggest sanitizing your value to remove everything except digits and a leading +, then using a better pattern on what's left.
And, it's just a cosmetic change but you can replace Rule::requiredIf(!request('national')), with a simple required_if rule like the others.
Changing to a form request validation, this would look like:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreFundingsource extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Prepare the data for validation.
*
* #return void
*/
protected function prepareForValidation()
{
$phone = preg_replace("/[^0-9]/", "", $this->phone);
if (strpos($this->phone, "+") === 0) {
$phone = "+$phone";
}
$this->merge(["phone"=>$phone]);
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => ['required'],
'description' => ['required'],
'national' => ['nullable'],
'province' => ['required_if,national,'],
'categories' => ['exists:categories,id']
'url' => [
'required_without:phone,email',
'active_url'
],
'phone' => [
'required_without:url,email',
'regex:/^\+?1?[2-9][0-9]{5,14}$/'
],
'email' => [
'required_without:url,phone',
'email:rfc,dns'
],
];
}
}

REST API, Laravel, Validation

I have a small question. I create simple API using Laravel. When I use validation and if it fails, I got a common message:
{
"result": false,
"message": "The given data failed to pass validation.",
"details": []
}
But how can I get details about which field fails and why like that:
{
"result":false,
"message":"The given data failed to pass validation.",
"details":{
"email":[
"The email field is required."
],
"password":[
"The password must be at least 3 characters."
]
}
}
My code in controller looks like this:
protected function validator(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3',
]);
return $validator;
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id' => 2
]);
}
It is better to handle the validator within the same process, like this:
public function register(Request $request){
$validator = Validator::make($request->all(),[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
if($validator->fails()){
return response()->json([
"error" => 'validation_error',
"message" => $validator->errors(),
], 422);
}
$request->merge(['password' => Hash::make($request->password)]);
try{
$user = User::create($request->all());
return response()->json(['status','registered successfully'],200);
}
catch(Exception $e){
return response()->json([
"error" => "could_not_register",
"message" => "Unable to register user"
], 400);
}
}
You should make sure you're sending the request with the Accept: application/json header.
Without that - Laravel won't detect that it's an API request,
If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
check the documentation
I used validate in my project:
1.I created app/http/requests/CreateUserRequestForm.php
public function rules()
{
return [
"name" => 'required',
"address" => 'required',
"phnumber" => 'required|numeric',
];
}
public function messages()
{
return [
'name.required' => 'Please Enter Name',
'addresss.required' => 'Please Enter Address',
'phnumber.required' => 'Please Enter PhNumber'
];
}
call the RequestForm in controller
use App\Http\Requests\CreateUserRequestForm;
public function createUser(CreateUserRequestForm $request)
{
// create
$user= UserModel::create([
'name' => $request->input('name'),
'address' => $request->input('address'),
'phnumber' => $request->input('phnumber')
]);
return response()->json(['User' => $user]);
}
Try this i didn't try but it should be work for you.
You may use the withValidator method. This method receives the fully
constructed validator, allowing you to call any of its methods before
the validation rules are actually evaluated.
take reference from here. laravel validation
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('email', 'Please enter valid email id');
}
});
}
Try this:
public function create(){
// ------ Validate -----
$this->vallidate($request,[
'enter code here`name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3'
]);
// ------ Create user -----
$user = User::create(['name' => $request->name']);
return response()->json([
'message' => "success",
'data' => $user``
]);
}

Laravel update password only if it is set

I am working on a laravel project with user login. The admin can create new users and edit existing users. I have got a password and a passwordConfirm field in the update-user-form. If the admin puts a new password in the form, it should check for validation and update the record in the db. If not, it shouldn't change the password (keep old one), but update the other user data (like the firstname).
If I try to send the form with an empty password and passwordConfirm field, it doesn't validate. I got a validation error, that the password must be a string and at least 6 characters long, but I don't know why. It seems like the first line of my update function will be ignored.
UserController.php
public function update(User $user, UserRequest $request) {
$data = $request->has('password') ? $request->all() : $request->except(['password', 'passwordConfirm']);
$user->update($data);
return redirect('/users');
}
UserRequest.php
public function rules() {
return [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'string|min:6',
'passwordConfirm' => 'required_with:password|same:password',
];
}
If you want to validate a field only when it is present then use sometimes validation rule in such cases.
Add sometimes validation to both password & passwordConfirm. Remove the $data line from update();
// UserController.php
public function update(User $user, UserRequest $request) {
$user->update($request->all());
return redirect('/users');
}
// UserRequest.php
public function rules() {
return [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'sometimes|required|string|min:6',
'passwordConfirm' => 'sometimes|required_with:password|same:password',
];
}
Reference - https://laravel.com/docs/5.4/validation#conditionally-adding-rules
I always do this in my projects:
//Your UserController file
public function update(User $user, UserRequest $request) {
$user->update($request->all());
return redirect('/users');
}
//Your UserRequest file
public function rules() {
$rules= [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255'
];
if($this->method()=="POST"){
$rules['password']='sometimes|required|string|min:6';
$rules['passwordConfirm']='sometimes|required_with:password|same:password';
}
return $rules;
}
So, as you can see if your method is POST it means that you want to add a new user so its going to ask for password and passwordConfirm but if your method is PATCH or PUT it means you don't need to validate password and passwordConfirm.
Hope it helps
Maybe you should try the following:
// ... more code
// Removes password field if it's null
if (!$request->password) {
unset($request['password']);
}
$request->validate([
// ... other fields,
'password' => 'sometimes|min:6'
// ... other fields,
]);
// ... more code
you should replace "has" with "filled" in your code
$data = $request->filled('password') ? $request->all() : $request->except(['password', 'passwordConfirm']);
and actually it's better if you use the expression like this
$request->request->remove('password_confirmation');
( ! $request->filled('password') ) ? $request->request->remove('password'):"";
( $request->has('password') ) ? $request->merge([ 'password' => Hash::make($request->post()['password']) ]):"";
//then you can use
$user->update($request->all());
Even better, however, you have to use separate request classes for create and update "php artisan make:request" for ex:
UserUpdateRequest.php and UserCreateRequest.php
for UserCreateRequest your rule is
'password' => 'required|confirmed|min:6',
for UserUpdateRequest your rule is
'password' => 'sometimes|nullable|confirmed|min:6',
and your controller head add this line
use App\Http\Requests\UserCreateRequest;
use App\Http\Requests\UserUpdateRequest;
and your update method must change
public function update(UserUpdateRequest $request, $id)
{
//
}
Standard way of doing this
UserRequest.php
first import Rule
use Illuminate\Validation\Rule;
in your rules array:
'password' => [Rule::requiredIf(fn () => $this->route()->method == "POST")]
Example:
public function rules()
{
return [
'name' => 'required',
'email' => ['required', 'email'],
'password' => [Rule::requiredIf(fn () => $this->route()->method == "POST"), 'confirmed'],
];
}
below php 7.4 use this way
'password' => [Rule::requiredIf(function(){
return $this->route()->method == "POST";
})]

Laravel: Validation unique on update

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]
];
}

Categories