Laravel 5.2 - Create custom validation message when extending Validator - php

In my AppServideProvider's boot method I've set a custom validation rule for cyrillic. Here is what it lookes like:
public function boot()
{
Validator::extend('cyrillic', function ($attribute, $value, $parameters, $validator) {
return preg_match('/[А-Яа-яЁё]/u', $value);
});
}
It works as expected. However if the validation doesn't pass because of latin input I get the error message 'validation.cyrillic'. How can I fix that? How can I pass a custom message to my 'cyrillic' validation rule?

If you want to define it globally, you need to edit the validation file or files, which is/are located in resources/lang/LANG/validation.php where LANG is whatever language you want to define is.
For instance, for the English ones, open the file resources/lang/en/validation.php and add your message like below.
return [
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
// Add yours to somewhere in the first level of the array
'cyrillic' => 'The :attribute is not Cyrillic.'
]
For locally, you can define it within a Request.
public function messages()
{
return [
'cyrillic' => 'The :attribute is not Cyrillic.'
];
}

Related

Customize Laravel API validation responses

I'm building a REST API with Laravel and wondering if there is a way to customize the API responses when validating.
For example, I have a validation rule in a Laravel request, saying a specific field is required.
public function rules() {
return [
'title'=>'required|min:4|max:100',
];
}
So, for this validation I get the error message in Postman like this
{
"title": [
"Please enter Ad Title"
]
}
What I want is to customize that response like this..
{
"success": false,
"message": "Validation Error"
"title": [
"Please enter Ad Title"
]
}
So, that the error is more specific and clear.
So, how to achieve this ?
Thanks!
I got a solution for your REST-API Validation Laravel FormRequest Validation Response are change by just write a few lines of code.
enter code here
Please add this two-line into your App\Http\Requests\PostRequest.php
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
after that add this function in your file.
you can change $response variable into your specific manner.
protected function failedValidation(Validator $validator) {
$response = [
'status' => false,
'message' => $validator->errors()->first(),
'data' => $validator->errors()
];
throw new HttpResponseException(response()->json($response, 200));
}
Provide a custom function to the FormRequest class called messages and return an array of validation messages mapped using dot notation for specific messages on specific rules:
public function messages()
{
return [
'title.required' => 'Please enter an Ad title',
'title.min' => 'Your title must be at least 4 character'
]
}
Returning a success message is futile as if it fails a 422 error code will be thrown when performing an ajax request anyway.
As for the message property, you will receive that as part of the payload, wherein the actual validation errors will be contained in the object.
You can customize errors, check the documentation. also you can validate in this way
$validator = Validator::make($request->all(), [
'title'=>'required|min:4|max:100'
]);
if ($validator->fails()) {
// get first error message
$error = $validator->errors()->first();
// get all errors
$errors = $validator->errors()->all();
}
then add them to your response, for example
return response()->json([
"success" => false,
"message" => "Validation Error"
"title" => $error // or $errors
]);

How can I declare a route and a controller method that explicitly expect two query parameters like this?

I am pretty new in Laravel and I have the following problem.
I have to declare a route that handle requests like this:
http://laravel.dev/activate?email=myemail#gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc
So this URL have to mantein this format (activate as resource and 2 query parameters in the form ?email and &token. This is not a REST URI. I need to use it in this way).
I need a route and a controller method that handle this kind of request.
I know that I can do something like this:
1) Into the routes/web.php file I declare a rout like this
Route::get('/activate','MyController#myMethod');
2) Into MyController I declare this method:
public function myMethod(Request $request) {
if(Input::has('email') && Input::has('token')) {
$email = $request->input('email');
$token= $request->input('token');
// DO SOMETHING USING $email AND $token
}
else {
// SHOW ERROR PAGE
}
}
But onestly I find it pretty horrible. I came from Java and using Spring framework I can specify in the mapping between the URL and the controller method that a method handle a request toward a resource and that to be handled some specific query paramer have to be passed. Otherwise (if these parameter are not present the HTTP GET request is not handled by the controller method).
I know that in Laravel I can do something like this using REST form of my URL, I think something like this:
For the route mapping:
Route::get('/activate/{email}/{token}', [ 'uses' => 'ActivationController#activate', 'as' => 'activate' ]);
And then the controller method will be something like this:
public function activate($email, $token) {
// $email would be 'myemail#gmail.com'
// $token would be 'eb0d89ba7a277621d7f1adf4c7803ebc'
// do stuff...
}
But I can't use this kind of URI in this case (as specified the URL pattern have to be in the format:
http://laravel.dev/activate?email=myemail#gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc
So I desire do something like this with this kind of URI. I don't wont to pass the Request $request object to my controller method and then extract the parameters from it but I want to have a controller method signature like this:
public function activate($email, $token) {
in which if all the expected parameters are not passed simply the request will not handled by this controller.
I prefer do it because for me is a neater approach (reading the controller signature another developer immediately know that this method is expecting).
And also because I want that malformed parameters are not handled by the method (so I can avoid to handle error cases like: the user not pass the 2 parameters).
How can I do something like this in Laravel? (if it is possible...)
This is certainly a strange request, because it defies a more traditional use of Laravel routing practices, but this should work for you:
In routes.php (Laravel < 5.3) or web.php (Laravel 5.4+):
Route::get('/activate', [ 'as' => 'activate', function()
{
return app()->make(App\Http\Controllers\ActivateController::class)->callAction('activate', $parameters = [ 'email' => request()->email, 'token' => request()->token ]);
}]);
So we are instantiating the ActivateController class and calling the method 'activate' which is the first argument, then supplying a list of parameters the method receives in the form of an array.
public function activate($email, $token)
{
echo "Email: $email"; // myemail#gmail.com
echo "Token: $token"; // eb0d89ba7a277621d7f1adf4c7803ebc
// do stuff
}
Now, provided you go to http://laravel.dev/activate?email=myemail#gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc $email and $token will be the respective key query parameters.
Now, as for validating to ensure that data is present. You have to add another argument to your activate() method, unless you want to do it inline.
The best practice way:
Run php artisan make:request ActivateRequest
A new file called ActivateRequest will be created in app\Http\Requests. Open it up and make sure your authorize() method returns true like so:
public function authorize()
{
return true;
}
Next, in the rules() method there is an array. Add the following:
return [
'email' => 'required|email',
'token' => 'required',
];
If you want to supply your own validation messages to these rules, add a method below rules() called messages() Like so:
public function messages()
{
return [
'email.required' => 'You must supply an email address.',
'email.email' => 'That email is address is not valid.',
'token.required' => 'Please supply a token.',
];
}
Then, back in ActivateController pull in your new FormRequest class at the top use App\Http\Requests\ActivateRequest; and use it in the method like so:
activate($email, $token, ActivateRequest $request) {
...
Now, your request will be validated and you don't even have to use the $request variable.
The inline (not so best practice way)
If you are dead set on not having an extra argument in your method, you can validate data in the controller like so:
First, bring in the Validator class at the top. use Validator;.
public function activate($email, $token)
{
$validationMessages = [
'email.required' => 'You must supply an email address.',
'email.email' => 'That email is address is not valid.',
'token.required' => 'Please supply a token.',
];
$validation = Validator::make(request()->toArray(), [
'email.required' => 'You must supply an email address.',
'email.email' => 'That email is address is not valid.',
'token.required' => 'Please supply a token.',
], $validationMessages);
if ( $validation->fails() )
{
return 'Sorry, there was a problem with your request';
}
// do stuff
}
Hope this helps.

Dynamically change CakePHP 3 custom validation rule message

I've got a custom validation method that checks a field for token values to ensure that they are all present in the content. The method works fine, it validates as OK when all the tokens exist in the content and throws a validation error when one or more tokens are missing.
I can easily apply a validation error message to state that some of the tokens are missing when I attach my custom validation rule to my table in validationDefault(). However, what I really want to do is set a validation message that reflects which of the tokens haven't been set. How can I dynamically set the validation message in CakePHP 3? In CakePHP 2 I used to use $this->invalidate() to apply an appropriate message, but this no longer appears to be an option.
My code looks like this (I've stripped out my actual token check as it isn't relevant to the issue here):-
public function validationDefault(Validator $validator)
{
$validator
->add('content', 'custom', [
'rule' => [$this, 'validateRequiredTokens'],
'message' => 'Some of the required tokens are not present'
]);
return $validator;
}
public function validateRequiredTokens($check, array $context)
{
$missingTokens = [];
// ... Check which tokens are missing and keep a record of these in $missingTokens ...
if (!empty($missingTokens)) {
// Want to update the validation message here to reflect the missing tokens.
$validationMessage = __('The following tokens are missing {0}', implode(',', $missingTokens));
return false;
}
return true;
}
Read the API docs.
Copy and paste:
EntityTrait::errors()
Sets the error messages for a field or a list of fields. When called without the second argument it returns the validation errors for the specified fields. If called with no arguments it returns all the validation error messages stored in this entity and any other nested entity.
// Sets the error messages for a single field
$entity->errors('salary', ['must be numeric', 'must be a positive number']);
// Returns the error messages for a single field
$entity->errors('salary');
// Returns all error messages indexed by field name
$entity->errors();
// Sets the error messages for multiple fields at once
$entity->errors(['salary' => ['message'], 'name' => ['another message']);
http://api.cakephp.org/3.3/class-Cake.Datasource.EntityTrait.html#_errors
Not sure if this is something that's been improved since burzums answer.
But it's actually pretty simple. A custom validation rule can return true (if the validation succeeds), false (if it doesn't), but you can also return a string. The string is interpreted as a false, but used for the error message.
So you can basically just do this:
public function validationDefault(Validator $validator)
{
$validator
->add('content', 'custom', [
'rule' => [$this, 'validateRequiredTokens'],
'message' => 'Some of the required tokens are not present'
]);
return $validator;
}
public function validateRequiredTokens($check, array $context)
{
$missingTokens = [];
if (!empty($missingTokens)) {
// Want to update the validation message here to reflect the missing tokens.
$validationMessage = __('The following tokens are missing {0}', implode(',', $missingTokens));
//Return error message instead of false
return $validationMessage;
}
return true;
}
From the CookBook:
Conditional/Dynamic Error Messages

How to get custom value in laravel 5 custom validation

I have created a new custom validation in Laravel 5.0 like below to match the exact length validation. I have also setup the message for this in validation.php
// app/Validators/CustomValidator.php
<?php namespace App\Validators;
use App;
use Illuminate\Validation\Validator;
class CustomValidator extends Validator
{
public function validateExactLength($attribute, $values, $params)
{
return ($params[0] === strlen($values));
}
}
// resources/lang/en/validation.php
"exact_length" => "The :attribute must be a :exact_length characters."
It works like charm and prints following message if it fails ...
"myFieldName must be a :exact_length characters."
Notice above the bold char, i.e. it does not replace it with the value that I have provided in Validation Request file which is
app/Http/Requests/StoreSmsPriceRequest.php
public function rules()
{
return [
'MyFieldName' => 'required|exact_length:6'
];
}
So the problem is does not print the required length in the error message. How can do that?

Laravel 5.1 - Custom validation language file

Is it possible to conditionally set a custom language file (e.g. resources/lang/en/validation_ajax.php) for a validation request? Just to be clear, I don't want to change the app language, just use another set of messages depending on the request origin.
When I make an ajax validation call I want to use different messages since I'm showing the error messages below the field itself. So there's no need to show the field name (label) again.
I know you can define labels on 'attributes' => [] but it's not worth the effort since I have so many fields in several languages.
I'm using a FormRequest (there's no manual call on the Controller just a type hint).
You can override the messages() method for a specific request (let's say login request). Let me show you: At first place, you need yo create a new custom Form Request, here we will define a custom message for email.required rule:
<?php namespace App\MyPackage\Requests;
use App\Http\Requests\Request;
class LoginRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
public function messages()
{
return [
'email.required' => 'how about the email?',
];
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => ['required', 'email'],
'password' => ['required', 'confirmed']
];
}
}
Only email.required rule message will be override. For password it will display the default message set at validation.php file.
Now, apply the form request at your controller function like a type hint:
class LoginController{
public function validateCredentials(LoginRequest $request){
// do tasks here if rules were success
}
}
And that is all. The messages() method is useful if you need are creating custom packages and you want to add/edit validation messages.
Update
If you need to carry the bag of messages on into your package's lang file then you can make the following changes:
At your package create your custom lang file:
MyPackage/resources/lang/en/validation.php
Add the messages keeping the same array's structure as project/resources/lang/en/validation.php file:
<?php
return [
'email' => [
'required' => 'how about the email?',
'email' => 'how about the email format?',
],
];
Finally, at your messages() method call the lang's line of your package respectively:
public function messages(){
return [
'email.required' => trans('myPackage::validation.email.required'),
'email.emial' => trans('myPackage::validation.email.valid'),
];
}

Categories