How to: validate the existence of a database relationship in Laravel 4? - php

I have a model Product that belongs to a Trend:
class Product extends Eloquent {
public function trend()
{
return $this->belongsTo('Trend');
}
}
And as part of my validation rules I would like to check that this relationship exists, and if not trigger an error using:
$validator = Validator::make(Input::all(), $rules, $messages);
if ($validator->fails())
{
... some redirection code here
is called. I have tried to use the validation exists like below, but it never fires.
$rules = array(
'brand_name' => 'required|min:3',
'blurb' => 'required',
'link' => 'required',
'trend' => 'exists:trends'
);
I have also tried a few variations on the exists method, but nothing ever seems to fire. I know that the instance I am testing on definitely doesn't have a relationship set.
What am I doing wrong here?
EDIT:
I see now from typing this out that I am validating the input and not the models values. How would I actually validate a model instance's properties instead?

I have the following code in a ExchangeRate class:
/**
* Return the validator for this exchange rate.
*
* #return Illuminate\Validation\Validator A validator instance.
*/
public function getValidator()
{
$params = array(
'from_currency_id' => $this->from_currency_id,
'to_currency_id' => $this->to_currency_id,
'valid_from' => $this->valid_from,
'rate' => $this->rate,
'organization_id' => $this->organization_id,
);
$rules = array(
'from_currency_id' => ['required', 'exists:currencies,id'],
'to_currency_id' => ['required', 'exists:currencies,id', 'different:from_currency_id'],
'valid_from' => ['required', 'date'],
'rate' => ['required', 'numeric', 'min:0.0'],
'organization_id' => ['required', 'exists:organizations,id'],
);
return Validator::make($params, $rules);
}
Of course, this ExchangeRate class also have the associations defined:
public function from_currency()
{
return $this->belongsTo('Currency', 'from_currency_id');
}
public function to_currency()
{
return $this->belongsTo('Currency', 'to_currency_id');
}
And all this glued together works like a clock:
$validator = $exchangeRate->getValidator();
if ($validator->fails())
throw new ValidationException($validator);

Related

Laravel dynamic validation

I'm using Laravel and I have a custom validation. I want to pass some value to the validation class and validate it against the DB so I keep all the validation logic in the validation class. Here's my code but the validation error is not triggered:
public function rules() {
$userCode = UserCode::getCode();
$rules = [
'name' => 'required|string',
'email' => 'required|email',
$userCode => 'unique:user_codes,code,'. $userCode
];
return $rules;
}
What am I doing wrong here? the validation is never triggered even if the value $userCode already exists in the DB. The validation is triggered if the request contains bad email for example.
Edit: I have this user_codes table that has a code column that must be kept unique. UserCode::getCode() produces this code. So I also want to check if this code is unique or not in the table user_codes before passing it to the controller. I already have the custom validator but the problem is that I want it to also validate this code. The validator works fine with the other request body. The problem is that this code is not passed from the request body but it is simply generated from another method.
You could do this using a FormRequest class with the prepareForValidation() method. It should look something like this:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class WhateverRequest extends FormRequest
{
protected function prepareForValidation(): void
{
$this->merge([
'user_code' => UserCode::getCode(),
]);
}
public function rules(): array
{
return [
'name' => 'required|string',
'email' => 'required|email',
'user_code' => 'unique:user_codes,code'
];
}
}
your question is not clear, I understand you have a column named by code
and you want to be unique, you can add usercode to request,
request()->merge(['userCode'=>$userCode]);
then
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => 'unique:user_codes,code,'.UserCode::getId().',id'
];
I answered what I understand from your question
Okay start with the following:
php artisan make:rule SomeAwesomeRule
Then edit that created Rule
class SomeAwesomeRule implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
//some logic that needs to be handled...
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return __('Some.nice.translated.message');
}
}
And then apply the rule
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => new SomeAwesomeRule(#this is a constructor so pass away)
];
see
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => 'unique:user_codes,code'
];
//or
$userCode="";
do{
$userCode = UserCode::getCode();
}
while(UserCode::where('code',$userCode)->first());
// after loop you sure the code is unique
$rules = [
'name' => 'required|string',
'email' => 'required|email',
];

dont want to edit particular field which is used in store and update functions

ProductController
public function store()
{
$product = Product::create($this->validateRequest());
return redirect('/product');
}
public function update(Product $product)
{
$product->update($this->validateRequest());
return redirect('/product');
}
private function validateRequest()
{
return request()->validate([
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'code' => ['required', 'alpha_dash','unique:products'],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
]);
}
here code has unique value from table products. but whenever I edit the form it says code has already taken. so how to execute this without edit the 'code'(its unique).
You can ignore certain ids during the unique check:
use Illuminate\Validation\Rule;
public function store()
{
Product::create($this->validateRequest(new Product()));
return redirect('/product');
}
public function update(Product $product)
{
$product->update($this->validateRequest($product));
return redirect('/product');
}
private function validateRequest(Product $product)
{
return request()->validate([
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'code' => ['required', 'alpha_dash', Rule::unique('products')->ignore($product)],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
]);
}
Here you either pass the existing model when updating or a new model instance when storing, so the call to $product->id either returns null when storing a new product so no product in the database is ignored, or the id when updating and then only that product is ignored.
From the docs:
Forcing A Unique Rule To Ignore A Given ID:
Sometimes, you may wish to ignore a given ID during the unique check.
For example, consider an "update profile" screen that includes the
user's name, e-mail address, and location. You will probably want to
verify that the e-mail address is unique. However, if the user only
changes the name field and not the e-mail field, you do not want a
validation error to be thrown because the user is already the owner of
the e-mail address.
To instruct the validator to ignore the user's ID, we'll use the Rule
class to fluently define the rule. In this example, we'll also specify
the validation rules as an array instead of using the | character to
delimit the rules:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Be aware of the following though:
You should never pass any user controlled request input into the
ignore method. Instead, you should only pass a system generated unique
ID such as an auto-incrementing ID or UUID from an Eloquent model
instance. Otherwise, your application will be vulnerable to an SQL
injection attack.
So the problem here is you are using the same rule for creating the product and updating the product.
If you are using the latest Laravel, you may want to read the documentation about form request https://laravel.com/docs/7.x/validation#form-request-validation and create different form request for store and update.
If you still want to use your way, you can try as below
private function validateRequest()
{
$rules = [
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
];
if (request()->isMethod('store')) {
$rules['code'] = ['required', 'alpha_dash'];
}
return request()->validate($rules);
}
Please tell me whether it works!
Try this, proper and clean code
ProductController
use Illuminate\Validation\Rule; // add this
public function store()
{
$product = Product::create($this->validateRequest());
return redirect('/product'); //use route instead of URL
}
public function update(Product $product)
{
$product->update($this->validateRequest($product->id));
return redirect('/product'); //use route instead of URL
}
private function validateRequest($id = null)
{
return request()->validate([
'sub_category_id' => 'required',
'name' => 'required|min:4',
'code' => 'required|alpha_dash|' . Rule::unique('products')->ignore($id),
'description' => 'required|min:4',
'color' => 'required|min:3',
'price' => 'required|integer',
]);
}
Suggest to use Form request validation

validate on array parameter igoners my rules and update

I have a function that updates the data. It receives the data as an array parameter.
I tried use validator make, and also validate helper method but it didn't work because it's only work for requests, and i tried also in validator make as the code below and also 'params.name' but it didn't work.
public function updateCompany(array $params): bool
{
if( Validator::make($params,[
'name'=> 'required|min:3|unique:company',
'email'=> 'required|min:4|unique:company|email'
])) {
return $this->update($params);
}
}
After trying this it didn't give me any error put it ignores my validation rules and update anyway.
Just use
public function updateCompany(Request $request)
then you could do something like this:
$rules = array('name' => 'required',
'email' => 'email|required|unique:users',
'name' => 'required|min:6|max:20');
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return ['status' => 422, 'errors' => $validator->errors()];
}

Custom Laravel validation messages

I'm trying to create customized messages for validation in Laravel 5. Here is what I have tried so far:
$messages = [
'required' => 'Harap bagian :attribute di isi.',
'unique' => ':attribute sudah digunakan',
];
$validator = Validator::make($request->all(), [
'username' => array('required','unique:Userlogin,username'),
'password' => 'required',
'email' => array('required','unique:Userlogin,email'),$messages
]);
if ($validator->fails()) {
return redirect('/')
->withErrors($validator) // send back all errors to the login form
->withInput();
} else {
return redirect('/')
->with('status', 'Kami sudah mengirimkan email, silahkan di konfirmasi');
}
But it's not working. The message is still the same as the default one. How can I fix this, so that I can use my custom messages?
Laravel 5.7.*
Also You can try something like this. For me is the easiest way to make custom messages in methods when you want to validate requests:
public function store()
{
request()->validate([
'file' => 'required',
'type' => 'required'
],
[
'file.required' => 'You have to choose the file!',
'type.required' => 'You have to choose type of the file!'
]);
}
If you use $this->validate() simplest one, then you should write code something like this..
$rules = [
'name' => 'required',
'email' => 'required|email',
'message' => 'required|max:250',
];
$customMessages = [
'required' => 'The :attribute field is required.'
];
$this->validate($request, $rules, $customMessages);
You can provide custom message like :
$rules = array(
'URL' => 'required|url'
);
$messages = array(
'URL.required' => 'URL is required.'
);
$validator = Validator::make( $request->all(), $rules, $messages );
if ( $validator->fails() )
{
return [
'success' => 0,
'message' => $validator->errors()->first()
];
}
or
The way you have tried, you missed Validator::replacer(), to replace the :variable
Validator::replacer('custom_validation_rule', function($message, $attribute, $rule, $parameters){
return str_replace(':foo', $parameters[0], $message);
});
You can read more from here and replacer from here
For Laravel 8.x, 7.x, 6.x
With the custom rule defined, you might use it in your controller validation like so :
$validatedData = $request->validate([
'f_name' => 'required|min:8',
'l_name' => 'required',
],
[
'f_name.required'=> 'Your First Name is Required', // custom message
'f_name.min'=> 'First Name Should be Minimum of 8 Character', // custom message
'l_name.required'=> 'Your Last Name is Required' // custom message
]
);
For localization you can use :
['f_name.required'=> trans('user.your first name is required'],
Hope this helps...
$rules = [
'username' => 'required,unique:Userlogin,username',
'password' => 'required',
'email' => 'required,unique:Userlogin,email'
];
$messages = [
'required' => 'The :attribute field is required.',
'unique' => ':attribute is already used'
];
$request->validate($rules,$messages);
//only if validation success code below will be executed
//Here is the shortest way of doing it.
$request->validate([
'username' => 'required|unique:Userlogin,username',
'password' => 'required',
'email' => 'required|unique:Userlogin,email'
],
[
'required' => 'The :attribute field is required.',
'unique' => ':attribute is already used'
]);
//The code below will be executed only if validation is correct.
run below command to create a custom rule on Laravel
ı assuming that name is CustomRule
php artisan make:rule CustomRule
and as a result, the command was created such as PHP code
if required keyword hasn't on Rules,That rule will not work
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class CustomRule implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
//return true or false
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The validation error message.';
}
}
and came time using that
first, we should create a request class if we have not
php artisan make:request CustomRequest
CustomRequest.php
<?php
namespace App\Http\Requests\Payment;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class CustomRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
return [
'custom' => ['required', new CustomRule()],
];
}
/**
* #return array|string[]
*/
public function messages(): array
{
return [
'custom.required' => ':attribute can not be empty.',
];
}
}
and on your controller, you should inject custom requests to the controller
your controller method
class FooController
{
public function bar(CustomRequest $request)
{
}
}
You can also use the methods setAttributeNames() and setCustomMessages(),
like this:
$validation = Validator::make($this->input, static::$rules);
$attributeNames = array(
'email' => 'E-mail',
'password' => 'Password'
);
$messages = [
'email.exists' => 'No user was found with this e-mail address'
];
$validation->setAttributeNames($attributeNames);
$validation->setCustomMessages($messages);
For those who didn't get this issue resolve (tested on Laravel 8.x):
$validated = Validator::make($request->all(),[
'code' => 'required|numeric'
],
[
'code.required'=> 'Code is Required', // custom message
'code.numeric'=> 'Code must be Number', // custom message
]
);
//Check the validation
if ($validated->fails())
{
return $validated->errors();
}
$rules = [
'name' => 'required',
'email' => 'required|email',
'message' => 'required|max:250',
];
$customMessages = [
'required' => 'The :attribute field is required.',
'max' => 'The :attribute field is may not be greater than :max.'
];
$this->validate($request, $rules, $customMessages);
In the case you are using Request as a separate file:
public function rules()
{
return [
'preparation_method' => 'required|string',
];
}
public function messages()
{
return [
'preparation_method.required' => 'Description is required',
];
}
Tested out in Laravel 6+
you can customise the message for different scenarios based on the request.
Just return a different message with a conditional.
<?php
namespace App\Rules;
use App\Helpers\QueryBuilderHelper;
use App\Models\Product;
use Illuminate\Contracts\Validation\Rule;
class ProductIsUnique implements Rule
{
private array $attributes;
private bool $hasAttributes;
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct(array $attributes)
{
$this->attributes = $attributes;
$this->hasAttributes = true;
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
$brandAttributeOptions = collect($this->attributes['relationships']['brand-attribute-options']['data'])->pluck('id');
$query = Product::query();
$query->when($brandAttributeOptions->isEmpty(), function ($query) use ($value) {
$query->where('name', $value);
$this->hasAttributes = false;
});
return !$query->exists();
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return ($this->hasAttributes) ? 'The Selected attributes & Product Name are not unique' : 'Product Name is not unique';
}
}
Laravel 10.x
If you are using Form Requests, add another method called messages(): array in your request.
class YourRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required',
'email' => 'required|email',
...
];
}
//Add the following method
public function messages(): array
{
return [
'email.required' => 'Custom message for Email Required',
];
}
}
Then the message will be displayed automatically once the request is send from the form.

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