Email validation rule in Laravel? - laravel-5

I do email validation using the simple rule:
'email' => 'required|email|unique:users,email',
How do I modify the option unique so that it will work only if the entered email is different from the primordial?
A sample:
The field email contains the default value from table users: example#gmail.com
Then I push the button without making any changes in the form I should not check unique:users.
Otherwise, if I even changed one symbol in example#gmail.com1 I must validate the incoming value using: unique:users.

You can find an example here https://laracasts.com/discuss/channels/requests/laravel-5-validation-request-how-to-handle-validation-on-update
You will need to have multiple rules depending on the request method (update or create) and you can pass a third parameter to unique to ensure no fail if you know the user / email
'user.email' => 'required|email|unique:users,email,'.$user->id,
Switch for method
switch($this->method())
{
...
}

I did this using the conditional checks:
$validator = Validator::make($request->all(), []);
$validator->sometimes('email', 'unique:users,email', function ($input) {
return $input->email !== Auth::user()->email;
});

I think it is as loophole in laravel validation.
I update the code for email validation. This is working fine for me.
'email' => [
'required', 'email:rfc',
function($attribute, $value, $fail) {
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$fail($attribute . ' is invalid.');
}
}],

Related

FormRequest messages() function does not translate all rules [duplicate]

I'm working on a Laravel 5.8 project and trying to show custom validation messages for a validation which uses the requiredIf validation rule.
Here is how I have it set up:
$validation = Validator::make(
$request->all(),
[
...
'sum' => [
Rule::requiredIf(function() use ($request){
$model = Model::find($request->id);
return $model->is_special; //returns a boolean value
}),
'numeric'
],
...
],
[
...
'sum.required_if' => 'This cannot be blank',
'sum.numeric' => 'Must use a number here',
...
]
);
Now the validation is working correctly and the custom message for the numeric validation shows as should, but the message I get for the requiredIf() method is Laravel's default error message.
I also tried using 'sum.requiredIf' => '...' but that didn't work either and can't seem to find any documentation or example for this scenario.
I was tinkering with this for a while and noticed that for this to work I needed to define
'sum.required' => 'This cannot be blank'
and not 'sum.required_if' => 'This cannot be blank',.
Not sure if this is expected behavior or just a workaround but my deduction is that with the callback Rule::requiredIf(function() use ($request){...}) the parameters :other and :value are not passed so it falls back onto required messaging and I guess this makes sense since required_if and required would not be used on the same :attribute.
Hope this helps anyone who comes across this problem.
First, create a rule name isSpecial or whatever
php artisan make:rule isSpecial
Go to App\Rules\isSpecial.php
private $id;
public function __construct($id) // pass id or what you need
{
//
$this->id=$id;
}
public function passes($attribute, $value) // customize your rules here
{
//
return Model::find($request->id)->is_special;
}
public function message() // here is answer for your question
{
return 'The validation error message.'; // your message
}
in your controller
use App\Rules\isSpecial;
\Validator::make($request->all(), [
'sum' => new isSpecial() ,
])->validate();
another idea :
Specifying Custom Messages In Language Files
In most cases, you will probably specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the resources/lang/xx/validation.php language file.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Simple notice:
- I suggest using HTTP Requests instead use validation in your controller and function direct
Looks like as of Laravel 8, using required_if works as expected, and alternatively will not fall back on required as mentioned previously:
'sum.required_if' => 'This cannot be blank',

Custom error message for `requiredIf` validation in laravel

I'm working on a Laravel 5.8 project and trying to show custom validation messages for a validation which uses the requiredIf validation rule.
Here is how I have it set up:
$validation = Validator::make(
$request->all(),
[
...
'sum' => [
Rule::requiredIf(function() use ($request){
$model = Model::find($request->id);
return $model->is_special; //returns a boolean value
}),
'numeric'
],
...
],
[
...
'sum.required_if' => 'This cannot be blank',
'sum.numeric' => 'Must use a number here',
...
]
);
Now the validation is working correctly and the custom message for the numeric validation shows as should, but the message I get for the requiredIf() method is Laravel's default error message.
I also tried using 'sum.requiredIf' => '...' but that didn't work either and can't seem to find any documentation or example for this scenario.
I was tinkering with this for a while and noticed that for this to work I needed to define
'sum.required' => 'This cannot be blank'
and not 'sum.required_if' => 'This cannot be blank',.
Not sure if this is expected behavior or just a workaround but my deduction is that with the callback Rule::requiredIf(function() use ($request){...}) the parameters :other and :value are not passed so it falls back onto required messaging and I guess this makes sense since required_if and required would not be used on the same :attribute.
Hope this helps anyone who comes across this problem.
First, create a rule name isSpecial or whatever
php artisan make:rule isSpecial
Go to App\Rules\isSpecial.php
private $id;
public function __construct($id) // pass id or what you need
{
//
$this->id=$id;
}
public function passes($attribute, $value) // customize your rules here
{
//
return Model::find($request->id)->is_special;
}
public function message() // here is answer for your question
{
return 'The validation error message.'; // your message
}
in your controller
use App\Rules\isSpecial;
\Validator::make($request->all(), [
'sum' => new isSpecial() ,
])->validate();
another idea :
Specifying Custom Messages In Language Files
In most cases, you will probably specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the resources/lang/xx/validation.php language file.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Simple notice:
- I suggest using HTTP Requests instead use validation in your controller and function direct
Looks like as of Laravel 8, using required_if works as expected, and alternatively will not fall back on required as mentioned previously:
'sum.required_if' => 'This cannot be blank',

Laravel validation exists in this table OR that table

I need to validate the existence of an API request parameter
but check it in one of two tables, users and teachers
something like this
$rules = ['apiToken' => 'required|string|min:70|exists:users,api_token ((OR)) exists:teachers,api_token']
is there a way to achieve this using Laravel validator?
For something like this you will probably need to use custom validation:
$rules = [
'apiToken' => [
'required', 'string', 'min:70', function ($attribute, $value, $fail) {
if (!DB::table('users')->where('api_token', $value)->exists() || !DB::table('teachers')->where('api_token', $value)->exists()) {
return $fail("The provided $attribute is not valid.");
}
}
]
];
You can change the returned error message by editing the text passed to the $fail function.

Laravel - exclude current email from unique validation

I am trying to use unique on an email address in Laravel 5.5 validation like this..
$rules = [
'email' => 'email|unique:users,email,
];
This is working and is checking the 'users' table in the 'email' column
But if the email address is the same as the currently saved one then this also fails validation.
Is there a way I can add an exception rule to the validation to ignore $user-email?
The unique rule takes a third parameter: a record to ignore, see "Forcing A Unique Rule To Ignore A Given ID".
Pass in the ID of the record you do not wish to be included in the unique test, e.g:
$rules = [
'email' => 'email|unique:users,email,' . $user->id
];
THIS IS AN EASY SOLUTION
Just add $this->route('id') as the third parameter
if your route was defined like this:
Route::put('{company}', 'CompanyController#update')
->name('update');
then your parameter name is "company"
So in your FormRequest:
public function rules()
{
$rules = [
'url' => [
'required',
'url',
'unique:companies,url,'.$this->route('company') ?? 0
],
];
// dd($rules); << check yourself
return $rules;
}
This FormRequest works the same for insert or update.
this line will instruct to ignore "0" in case of insert
$this->route('company') ?? 0

Using form request specific custom validation attributes

Using Laravel's localization (http://laravel.com/docs/5.1/localization) I have created some custom validation attributes to provide friendlier validation errors (for instance, 'First Name' instead of first name etc).
I am using form requests (http://laravel.com/docs/5.1/validation#form-request-validation) in order to validate user submissions and there are scenarios where I would like to provide store-specific custom validation attributes (for instance, I may have a 'name' field that is Brand Name in one context, and Product Name in another).
The messages() method allows me to specify validation rule specific message overrides, but that isn't ideal as it's not the validation message as such we need to override, just the attribute name (for example, if we have 5 validation rules for 'email', we have to provide 5 overrides here, rather than one override for, let's say, Customer Email).
Is there a solution to this? I note references to formatValidationErrors() and formatErrors() in the Laravel documentation, but there is not really any information on how to correctly override these, and I've not had much luck in trying.
You can override the attribute names, which is defaulting to whatever the field name is.
With form request
In your form request class override the attributes() method:
public function attributes()
{
return [
'this_is_my_field' => 'Custom Field'
];
}
With controller or custom validation
You can use the 4th argument to override the field names:
$this->validate($request, $rules, $messages, $customAttributes);
or
Validator::make($data, $rules, $messages, $customAttributes);
Simple working example
Route::get('/', function () {
// The data to validate
$data = [
'this_is_my_field' => null
];
// Rules for the validator
$rules = [
'this_is_my_field' => 'required',
];
// Custom error messages
$messages = [
'required' => 'The message for :attribute is overwritten'
];
// Custom field names
$customAttributes = [
'this_is_my_field' => 'Custom Field'
];
$validator = Validator::make($data, $rules, $messages, $customAttributes);
if ($validator->fails()) {
dd($validator->messages());
}
dd('Validation passed!');
});
As detailed in my question, I was looking for a way to provide specific form request stores (http://laravel.com/docs/5.1/validation#form-request-validation) with custom attribute names.
The Laravel documentation only covers two methods for Requests in this context - rules() and authorize(). I was aware there is a messages() method to provide validation specific custom error messages, but it also appears there is an attributes() method, which fits my requirements exactly:
public function attributes()
{
return [
'name' => 'Product Name'
]
}
This overrides the attribute name in the context of my store.

Resources