Laravel Custom Message - laravel

Hi I am working with custom validation with laravel I am new in this right now my controller code is mention this is how I am validating the upload file.
Everything is working but I have issue displaying custom message on view page
it shows the default message not my custom message Please have a look and let me know if I am doing something wrong.
$this->validate(
$request, [
'project_file.*' => 'required|size:2048',
],
[
'project_file.required' => 'Upload File Field Is Required',
'project_file.max' => 'Upload File Field Must Be 2MB',
]
);
$messages = [
'required' => 'The File should not be more then 2Mb',
'size' => 'The must be exactly Mb.',
];
$validator = Validator::make($input, $rules, $messages);
if($validator->fails()) {
return Redirect::back()->withErrors($validator);
}
My View code to display error is:
#if ($errors->any())
<div class="alert alert-danger">
<strong>{!! implode('', $errors->all('<div>:message</div>')) !!}</strong>
</div>
#endif

I feel the issue might be because you have not passed the field name placeholder in the messages array.
You can add custom error messages for your validations. You can pass a third parameter Validator::make method.
$messages = [ 'required' => 'The :field should not be more then 2Mb' ];
$validator = Validator::make($input, $rules, $messages);
The :field place-holder will be replaced by the field name
Adding custom error messages only for a specific field using dot operation
$messages = [
'file.required' => 'The image should not be more then 2Mb',
];
Hope this helps.

It's better approach not to write validation logic in the controller because it results fat controller and quite messy controller so you can use separate request class to do in better way.
At first, use following command in console to create custom validation request class like this,
php artisan make:request PostRequest
Now, a file named PostRequest.php will be created at the app/Http/Requests/ in that file you should make validation like following.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
'project_file.*' => 'required|max:2048',
];
}
public function messages()
{
return [
'required' => 'Upload File Field Is Required',
'max' => 'The File should not be more then 2Mb',
];
}
}
Now, function in which form request is passed you have to change Request to PostRequest like this so that validation is performed automatically.
public function post(PostRequest $request){
//
}

Related

Laravel avoid duplicate entry from model

I'm building a Laravel API. I have a models called Reservations. I want to avoid that a user creates two reservations for the same product and time period.
I have the following:
$reservation = Reservation::firstOrCreate([
'listing_id' => $request->listing_id,
'user_id_from' => $request->user_id_from,
'start_date' => $request->start_date,
'end_date' => $request->end_date,
]);
Edit after comments:
I'm also using validation
$validator = Validator::make($request->all(), [
'listing_id' => 'required|exists:listings,id',
'user_id_from' => 'required|exists:users,id',
'start_date' => 'required|date_format:"Y-m-d"|after:today',
'end_date' => 'required|date_format:"Y-m-d"|after:start_date'
]);
if ($validator->fails()) {
return response()->json(['error' => 'Validation failed'], 403);
}
Validation is working properly.
End of Edit
In my model I have casted the start_date and end_date as dates.
class Reservation extends Model
{
protected $fillable = ['listing_id', 'start_date', 'end_date'];
protected $dates = [
'start_date',
'end_date'
];
....
....
Documentation says:
The firstOrCreate method will attempt to locate a database record
using the given column / value pairs
However I notice that I'm still able to insert entries with the same attributes.
Any idea what I'm doing wrong or suggestions to fix it?
Probably there's a better way than this, but you can create an static method on Reservation to do this, like:
public static function createWithRules($data) {
$exists = $this->where('product_id', $data['product_id'])->whereBetween(*date logic that i don't remember right now*)->first();
if(!$exists) {
* insert logic *
} else {
* product with date exists *
}
}
So you can call Reservation::createWithRules($data)
You can achieve this using Laravel's built in ValidateRequest class. The most simple use-case for this validation, is to call it directly in your store() method like this:
public function store(){
$this->validate($request, [
'listing_id' => 'required|unique,
'start_date' => 'required|unique,
//... and so on
], $this->messages);
$reservation = Reservation::firstOrCreate([
'listing_id' => $request->listing_id,
'user_id_from' => $request->user_id_from,
'start_date' => $request->start_date,
'end_date' => $request->end_date,
]);
}
With this, you're validating users $request with by saying that specified columns are required and that they need to be unique, in order for validation to pass.
In your controller, you can also create messages function to display error messages, if the condition isn't met.
private $messages = [
'listing_id.required' => 'Listing_id is required',
'title.unique' => 'Listing_id already exists',
//... and so on
];
You can also achieve this by creating a new custom validation class:
php artisan make:request StoreReservation
The generated class will be placed in the app/Http/Requests directory. Now, you can add a few validation rules to the rules method:
public function rules()
{
return [
'listing_id' => 'required|unique,
'start_date' => 'required|unique,
//... and so on
];
}
All you need to do now is type-hint the request on your controller method. The incoming form request is validated before the controller method is called, meaning you do not need to clutter your controller with any validation logic:
public function store(StoreReservation $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}
If you have any additional question about this, feel free to ask. Source: Laravel official documentation.

Validating not all fields in form - Laravel

In laravel, I have created a form. At the moment, I am working on the validation of the input fields of this form. I ran into a problem when I tried to validate some input fields and others not. For example, mail should be validated but catering_name not (it isn't necessary to fill in this field, its an option)
I have tried all validation methods I could find. I keep getting the same error.
Method Illuminate\Validation\Validator::validatePhone does not exist.
I guess I am missing something.
I have tried:
Validator::make($request->...
$this->validate(request(), [ ...
$request->validate([ ...
Bellow, you will find all the data that should be inputted in the database.
If I remove the validation part, the data got inserted into the database. I think the problem lays with how I try to validate. Thanks for any help.
$this->validate(request(), [
'add_name' => 'required|min:3',
'add_mail' => 'required|email',
'name' => 'required|min:3',
'email' => 'required|email',
'telefone' => 'numeric|phone',
'gsm' => 'numeric|phone',
'event' => 'required|min:3',
'date_start' => 'required|date|after:tomorrow',
'date_end' => 'required|date|after_or_equal:event_date_start',
'location' => 'required|min:3',
'number' => 'required',
]);
$event = new Event;
$event->add_name = request('add_name');
$event->add_mail = request('add_mail');
$event->name = request('name');
$event->email = request('email');
$event->telefone = request('telefone');
$event->gsm = request('gsm');
$event->name = request('name');
$event->date_start = request('date_start');
$event->date_end = request('date_end');
$event->location = request('location');
$event->number = request('number');
$event->catering = request('catering');
$event->catering_name = request('catering_name');
$event->remarks = request('remarks');
$event->status = Event::STATUS_0;
$event->save();
Unfortunately phone is not one of the default validation. You can try something like:
[
'telefone' => 'required|regex:/(01)[0-9]{9}/',
]
You can see the available list of validations given by Laravel here.
There are a wide variety of more complex options depending on how important it is to you.
There are packages for easy plug and play like Laravel-Phone.
You can create your own custom validation using php artisan make:rule phone_number and then editing the new rule made:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class PhoneNumber implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
// logic here, most likely some sort of regex.
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be a valid phone number.';
}
}

Laravel action when form validation generates error

I am working with a form request file like this:
ProjectCreateRequest.php
public function rules()
{
$project_name = $this->project_name;
$meta_activity = $this->meta_activity;
return [
'project_name' => 'required|max:255|unique:projects',
'customer_name' => 'required|max:255',
'otl_project_code' => 'sometimes|max:255|unique:projects,otl_project_code,NULL,id,meta_activity,'.$meta_activity,
'estimated_start_date' => 'date',
'estimated_end_date' => 'date',
'LoE_onshore' => 'numeric',
'LoE_nearshore' => 'numeric',
'LoE_offshore' => 'numeric',
'LoE_contractor' => 'numeric',
'revenue' => 'numeric',
'win_ratio' => 'integer'
];
}
There is the otl_project_code that must be unique with the meta_activity.
In case someone enters a pair of otl_project_code and meta_activity that already exists, it goes back to the create page with the error written below.
I would like to get instead that in the controller, I can catch this information, do something on the database then redirect to an update url.
Because I am working with a form validation request file, everything is entered in my controller like this:
public function postFormCreate(ProjectCreateRequest $request)
and I don't know how to catch this specific error in my controller to execute some actions with all the fields I submitted and not go back to the create page. Of course, this needs to happen only when there is the specific error I mentionned above.
Override the FormRequest response function in your ProjectCreateRequest:
/**
* Get the proper failed validation response for the request.
*
* #param array $errors
* #return \Symfony\Component\HttpFoundation\Response
*/
public function response(array $errors)
{
if ($this->expectsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
That's the public response on the FormRequest class so you can write your own logic to perform DB queries and redirect where needed.

Date validation - How localize/translate strings "today" and "tomorrow"

In my model I defined a few validation rules for date fields using before and after:
'birth_date' => 'required|date|before:today|after:01-jan-1920',
'another_date' => 'required|date|before:tomorrow|after:01-jan-1990',
The validation works fine, however I can't figure out how to translate the strings today and tomorrow on the validation message.
In the validation.php language file the after and before messages are localizable, however the :date part of the message is still displaying the English version for today and tomorrow.
"after" => "The :attribute must be a date after :date.",
"before" => "The :attribute must be a date before :date.",
How could I localize those two words - today and tomorrow - in the validation message?
In short, add following code into resources/lang/whichever/validation.php
'values' => [
// or whatever fields you wanna translate
'birth_date' => [
// or tomorrow
'today' => '今天'
]
]
Explained:
https://github.com/laravel/framework/blob/7.x/src/Illuminate/Validation/Concerns/FormatsMessages.php#L319
/**
* Get the displayable name of the value.
*
* #param string $attribute
* #param mixed $value
* #return string
*/
public function getDisplayableValue($attribute, $value)
{
if (isset($this->customValues[$attribute][$value])) {
return $this->customValues[$attribute][$value];
}
// the key we want
$key = "validation.values.{$attribute}.{$value}";
// if the translate found, then use it
if (($line = $this->translator->get($key)) !== $key) {
return $line;
}
if (is_bool($value)) {
return $value ? 'true' : 'false';
}
return $value;
}
You can use custom validation messages per field, either on validation language file or in your code itself: https://laravel.com/docs/5.2/validation#custom-error-messages
Let's simulate a controller validation to see how it works:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class YourController extends Controller
{
public function store(Request $request)
{
$rules = [
'birth_date' => 'required|date|before:today|after:01-jan-1920',
];
$messages = [
'birth_date.before' => 'A data de nascimento deve ser uma data antes de hoje.', // "The birth date must be a date before today" in portuguese
];
$this->validate($request, $rules, $messages);
/* your stuff */
}
}
You can also do that with form requests (which are even nicer), all you need to do is return your custom translated messages inside messages() method. :)
Use custom error messages.
$this->validate(
$request,
[
'phone' => 'required|regex:/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i'
],
[
'regex' => 'You must enter a valid phone number.',
'required' => 'You must enter a valid phone number.'
]
);
Replace 'regex' and 'required' with 'before:today' and 'before:tomorrow' and replace with custom error messages.
It probably makes more sense to make some custom validations but I think you should be able to do this simply with Carbon:
$dt = new Carbon\Carbon();
$today = $dt->today();
$tomorrow = $dt->tomorrow();
$rules = [
...
'birth_date' => 'required|date|before:'.$today.'|after:01-jan-1920',
'another_date' => 'required|date|before:'.$tomorrow.'|after:01-jan-1990'
];

How to specify the default error message when extending the Validation class in Laravel 4

I use made use the extend function to extend and adding custom rules on the Validation Class of Laravel 4.
Validator::extend('foo', function($attribute, $value, $parameters)
{
return $value == 'foo';
});
When I validate the rule using the newly created custom extension, it returns validation.foo if the rule fails. Is there a way to define a generic/ default message when extending the validation class in Laravel 4?
The Laravel 4 docs specifically state you need to define an error message for your custom rules.
You have two options;
Option 1:
$messages = array(
'foo' => 'The :attribute field is foo.',
);
$validator = Validator::make($input, $rules, $messages);
Option 2:
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 app/lang/xx/validation.php language file:
'custom' => array(
'foo' => array(
'required' => 'We need to know your foo!',
),
),
In case someone is wondering about Laravel 5: just add your message to validation.php right under all the default messages. For example:
<?php
return [
// .. lots of Laravel code omitted for brevity ...
"timezone" => "The :attribute must be a valid zone.",
/* your custom global validation messages for your custom validator follow below */
"date_not_in_future" => "Date :attribute may not be in future.",
where date_not_in_future is your custom function validateDateNotInFuture.
Laravel will pick the message each time you use your rule for any field and you won't have to use custom array unless you want to override your global message for specific fields.
Full code to implement the validator follows.
Custom Validator (with a bonus gotcha comments for date_format and date_before localization):
<?php namespace App\Services\Validation;
use Illuminate\Validation\Validator as BaseValidator;
/**
* Class for your custom validation functions
*/
class Validator extends BaseValidator {
public function validateDateNotInFuture($attribute, $value, $parameters)
{
// you could also test if the string is a date at all
// and if it matches your app specific format
// calling $this->validateDateFormat validator with your app's format
// loaded from \Config::get, but be careful -
// Laravel has hard-coded checks for DateFormat rule
// to extract correct format from it if it exists,
// and then use for validateBefore. If you have some unusual format
// and date_format has not been applied to the field,
// then validateBefore will give unpredictable results.
// Your best bet then is to override protected function
// getDateFormat($attribute) to return your app specific format
$tomorrow = date('your app date format here', strtotime("tomorrow"));
$parameters[0] = $tomorrow;
return $this->validateBefore($attribute, $value, $parameters);
}
}
ValidatorServiceProvider file:
<?php namespace App\Providers;
namespace App\Providers;
use App\Services\Validation\Validator;
use Illuminate\Support\ServiceProvider;
class ValidatorServiceProvider extends ServiceProvider{
public function boot()
{
\Validator::resolver(function($translator, $data, $rules, $messages)
{
return new Validator($translator, $data, $rules, $messages);
});
}
public function register()
{
}
}
And then just add a line to config/app.php:
'App\Providers\RouteServiceProvider',
'App\Providers\ValidatorServiceProvider', // your custom validation
In addition to what TheShiftExchange has said, if you look in that validation.php language file you'll see all of the different rules that you can specify. So for instance, if your validator has entries like this:
class ArticleValidator extends Validator
{
public static $rules = [
'create' => [
'title' => ['required'],
'slug' => ['required', 'regex:([a-z\0-9\-]*)']
]
];
}
Then your custom validation rules may look like this:
'custom' => array(
'company_article_type_id' => array(
'required' => 'The slug field is really important',
'exists' => 'The slug already exists',
),
),
Notice how the 'required' and 'exists' keys in the custom validation rules match those in the validator above.

Resources