Laravel 5: How to insert error custom messages array inside validate() - validation

I want to insert my validation custom messages inside the validate function as shown:
public function postLogin(Request $request)
{
$rulesemail=['required'=>'Este campo es requerido.'];
$rulespassword=['min'=>'Debe teclear al menos :min caracteres','required'=>'Favor de teclear su contraseƱa'];
$this->validate($request, [
'email' => 'required|email|max:60', 'password' => 'required|min:6'],$rulespassword
);
But i can't get it to work. Any ideas?

You can't with the default validate() from the ValidatesRequests trait.
However you can override the function in your base controller to change that:
public function validate(Request $request, array $rules, array $messages = array())
{
$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages);
if ($validator->fails())
{
$this->throwValidationException($request, $validator);
}
}
And then simply pass the custom messages as third parameter:
$rulesemail=['required'=>'Este campo es requerido.'];
$messages=['min'=>'Debe teclear al menos :min caracteres','required'=>'Favor de teclear su contraseƱa'];
$this->validate($request, [
'email' => 'required|email|max:60',
'password' => 'required|min:6'
], $messages);
Remember that you can also globally define validation messages in a language file. This file is usually located at resources/lang/xx/validation.php

The validate() method accepts 3 parameters:
Request $request, [$errors], [$messages]
Here's an example of how to customise the error message for a validation condition:
$this->validate(
$request,
[
'first_name'=> 'required',
'last_name'=> 'required',
'email' => 'email',
'date_of_birth' => 'date_format:"Y-m-d"'
],
[
'date_format' => 'DOB'
]
);
PHPStorm provides useful tooltip to instantly see the method options.

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

check if validation fails (with custom mesages)

When using the validation like below with custom messages how is possible to check if the validation fails?
$rules = [
'email' => 'required|email'
];
$customMessages = [
'email.required' => 'The email is required.',
'email.email' => 'Please insert a valid email.'
];
$this->validate($request, $rules, $customMessages);
Like below, without custom messages is possible to use $validator->fails() but in the above case how to verify if the validation fails?
$validator = Validator::make($request->all(), [
//...
]);
if ($validator->fails()) {
//...
}
When you use $this->validate it validate your request against your validation rules and if failed then it redirect to previous page with validation message. If you want to use $validator->fails() then use Validator::make with custom message. Like this
$rules = [
'email' => 'required|email'
];
$customMessages = [
'email.required' => 'The email is required.',
'email.email' => 'Please insert a valid email.'
];
$validator = Validator::make($request->all(), $rules, $customMessages);
if ($validator->fails()) {
//...
}
Check validator make method https://laravel.com/api/5.0/Illuminate/Validation/Factory.html#method_make
much simpler solution is to use custom handler in app\Exceptions\Handler.php:
public function register()
{
$this->renderable(function (ValidationException $e, $request) {
//list of specific failed tests
$e->validator->failed();
return response()->json(['message' => 'custom message','meow'=>'meow',$e->status);
});
}
this way you keep old behavior AND can still change messages sent back to the user/frontend

Laravel Custom Validation - Mailgun API

I'm trying to implement one of Laravel's new features "Custom Validation Rules" and I'm running into the following error:
Object of class Illuminate\Validation\Validator could not be converted to string
I'm following the steps in this video:
New in Laravel 5.5: Project: Custom validation rule classes (10/14)
It's an attempt Mailgun API's Email Validation tool.
Simple form that requests: first name, last name, company, email and message
Here is my code:
web.php
Route::post('contact', 'StaticPageController#postContact');
StaticPageController.php
use Validator;
use App\Http\Validation\ValidEmail as ValidEmail;
public function postContact(Request $request) {
return Validator::make($request->all(), [
'firstname' => 'required|max:90',
'lastname' => 'required|max:120',
'company' => 'max:120',
'email' => [
'required', 'string', 'max:255',
new ValidEmail(new \GuzzleHttp\Client)
],
'message' => 'required',
]);
}
ValidEmail.php
<?php
namespace App\Http\Validation;
use Illuminate\Contracts\Validation\Rule;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client as Guzzle;
class ValidEmail implements Rule
{
protected $client;
protected $message = 'Sorry, invalid email address.';
public function __construct(Guzzle $client)
{
$this->client = $client;
}
public function passes($attribute, $value)
{
$response = $this->getMailgunResponse($value);
}
public function message()
{
return $this->message;
}
protected function getMailgunResponse($address)
{
$request = $this->client->request('GET', 'https://api.mailgun.net/v3/address/validate', [
'query' => [
'api_key' => env('MAILGUN_KEY'),
'address' => $address
]
]);
dd(json_decode($request->getBody()));
}
}
Expectation
I'm expecting to see something like this:
{
+"address": "test#e2.com"
+"did_you_mean": null
+"is_disposable_address": false
+"is_role_address": false
+"is_valid": false
+"parts": {
...
}
}
Any help is much appreciated. I've been trying to get this simple example to work for over two hours now. Hopefully someone with my experience can help!
In your controller
Try this:
$validator = Validator::make($request->all(), [
'firstname' => 'required|max:90',
'lastname' => 'required|max:120',
'company' => 'max:120',
'email' => [
'required', 'string', 'max:255',
new ValidEmail(new \GuzzleHttp\Client)
],
'message' => 'required',
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
// if valid ...
According to your route, the postContact method is the method to handle the route. That means the return value of this method should be the response you want to see.
You are returning a Validator object, and then Laravel is attempting to convert that to a string for the response. Validator objects cannot be converted to strings.
You need to do the validation, and then return the correct response based on that validation. You can read more about manual validators in the documenation here.
In short, you need something like this:
public function postContact(Request $request) {
$validator = Validator::make($request->all(), [
'firstname' => 'required|max:90',
'lastname' => 'required|max:120',
'company' => 'max:120',
'email' => [
'required', 'string', 'max:255',
new ValidEmail(new \GuzzleHttp\Client)
],
'message' => 'required',
]);
// do your validation
if ($validator->fails()) {
// return your response for failed validation
}
// return your response on successful validation
}

How can I compare the inputs to some specific data in laravel validation

I am making an web application and I want only those people knowing a special code can register. How should I do it or check the code entered by the user on the registration form..the validator function in RegisterController has this code:- .
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'place' => 'required|max:255',
'password' => 'required|min:6|confirmed',
]);
}
what inclusion should I made.?
In case you want to store the registration codes in a separate table, you can do this in your validator.
codes
id - integer
code - string
Validation logic
'code' => 'required|exists:codes',
If you want to use a custom column name to validate then you can do this
'code' => 'required|exists:codes,columnName',
If the code is a simple hardcoded value then you can write a custom validation rule and use it.
Add this in the boot method of AppServiceProvider
Validator::extend('registration_code', function ($attribute, $value, $parameters, $validator) {
return $value === 'supersecretcode';
});
Validation logic
'code' => 'required|registration_code,
You can use this if you are using a controller !!!
public function validator(Request $request)
{
// validation
$this->validate($request, array(
'title' => 'required|max:255',
'slug' => 'required|alpha_dash|min:5|max:255|unique:posts,slug',
'body' => 'required'
));

L5 custom validation messages not displayed

I'm using the following code in my controller action for validation. I'm 100% sure this is the code that's being used for the validation as removing and adding validations is working as expected:
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
], [
'email.required' => 'Vul een e-mailadres in.',
'email.email' => 'Vul een geldig e-mailadres in.',
'password.required' => 'Vul een wachtwoord in.'
]);
The problem is that it keeps showing the default error messages ("The email field is required.") instead of the messages I'm providing ("Vul een e-mailadres in.").
I'm using the following code to display the errors in the view:
{{ $errors->first('email') }}
I guess this is the right way to do this, because when I choose Go To Declaration of the validate method in PhpStorm I see the following function:
vendor\laravel\framework\src\Illuminate\Foundation\Validation\ValidatesRequests.php:
public function validate(Request $request, array $rules, array $messages = array())
{
$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages);
if ($validator->fails())
{
$this->throwValidationException($request, $validator);
}
}
Why does it keep displaying the default error messages?
The problem is, that controller validation uses ValidatesRequests and validate method is defined this way:
public function validate(Request $request, array $rules)
{
$validator = $this->getValidationFactory()->make($request->all(), $rules);
if ($validator->fails())
{
$this->throwValidationException($request, $validator);
}
}
You cannot pass here translation. However in your case you should just create validation.php file with your translation in resources/lang/nl directory and in your config/app.php file set locale to nl
EDIT
I've looked at source and in newer Laravel 5 version, indeed 3rd parameter is used. It seems that new parameter was added and you have old version in compiled file (maybe you have modified composer.json or old composer.json file).
Whenever you have similiar issues you should run in your console:
php artisan clear-compiled
to remove compiled files.
If you don't want to have this file when development, you could remove it from composer.json file - you should remove lines with "php artisan optimize" however it will affect app performance if you don't restore it and generated new compiled.php mfile when running in production.
You can use the Validato::make() method.
$data = Input::all();
$rules = array(
'email' => 'required|email',
'password' => 'required'
);
$messages = array(
'email.required' => 'Vul een e-mailadres in.',
'email.email' => 'Vul een geldig e-mailadres in.',
'password.required' => 'Vul een wachtwoord in.'
);
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails())
{
return Response::json(['error' => $validator->errors()->first()]);
}

Resources