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

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

Related

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.';
}
}

In Laravel how can I validate an select option multiply type array (name[])?

Validate a named select option input type name[] multiply in the validation options that have laravel version 5.6?
According to the documentation, I tried to validate it that way, but it doesn't work for me
One way
<select name="office[]">
$validator = Validator::make($request->all(), [
'office.*' => 'required'
], [
'office.required' => __('My message')
]);
Otra que tampoco me funciona
$validator = Validator::make($request->all(), [
'office' => "required|array|min:1",
"office.*" => "required|integer|min:1",
], [
'office.*.required' => __('Debes agregar alguna sucursal')
]);
I could be helped by please !!!
PS:I'm with version 5.6.*
For something as complex as an array I would use Custom Validation. That would allow you to write a function and pass the validation however you want.
public function passes($attribute, $value)
{
if(/** Array complies with your rules **/) {
return true;
}
}

How to validate only part of a value I'm getting through a get request?

I want to get two values from a get request, and then I'll use explode to retrieve each of them separately. However, this means that the value I'm getting before using explode isn't unique to the table (since it's a compound, and therefore it's not an existing value in the table). How can use validate to avoid duplicate of it ?
I tried making the column unique using an SQL constraint, however this means I get an exception page when a user enters a duplicate. I would like to use validation instead so I get an error message.
public function store(Request $request)
{
$this->validate($request, [
'idProduit' => 'unique:stocks',
'produit' => 'required|unique:stocks',
'quantite' => 'required'
]);
$produit = explode("|",$request->get('produit'));
$stock = new Stock;
$stock->idProduit = $produit[0];
$stock->produit = $produit[1];
$stock->quantite = $request->input('quantite');
$stock->save();
return redirect('/stocks/')->with('success', 'Entrée de stock ajoutée à la base de données');
}
I don't actually get any error message, but it is allowing me to add duplicates in the database, which I know why : the value is a compound that doesn't exist in the database, and so the unique validation I wrote cannot catch duplicate on just a part of it.
You could create custom validation rule class or use Validator https://laravel.com/docs/5.8/validation#custom-validation-rules.
Something like that:
Validator::make($request->all(), [
'quantite' => 'required',
'produit' => [
'required',
function ($attribute, $value, $fail) {
$parts = explode('|', $value);
if (!Stock::where('idProduit', $parts[0])->exists()) {
$fail('idProduit already exists.');
}
if (!Stock::where('produit', $parts[1])->exists()) {
$fail('produit already exists.');
}
}
],
])->validate();
Easy way : Explode before validation and make new $request with 2 more fields . Thats Over !!
public function store(Request $request)
{
$produit = explode("|",$request->get('produit'));
$request->request->add(['idProduit' => $produit[0]]);
$request->request->add(['produit' => $produit[1]]);
$this->validate($request, [
'idProduit' => 'unique:stocks',
'produit' => 'required|unique:stocks',
'quantite' => 'required'
]);
$stock = new Stock;
$stock->idProduit = $produit[0];
$stock->produit = $produit[1];
$stock->quantite = $request->input('quantite');
$stock->save();
return redirect('/stocks/')->with('success', 'Entrée de stock ajoutée à la base de données');
}

Laravel Custom Message

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){
//
}

TimestampBehavior does not work because of failing validation

I have the following class with a TimestampBehaviour:
/**
* #property int $id
* #property string $name
* #property int $created_at
*/
class Workspace extends yii\db\ActiveRecord {
public static function tableName() {
return 'workspace';
}
public function behaviors() {
return [
[
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'created_at',
ActiveRecord::EVENT_BEFORE_UPDATE => false,
],
'value' => date('Y-m-d H:i:s')
],
];
}
...
}
For some reason the behavior does not populate the property. It is always empty when I try to save the model ($workspace->save()). I cannot save it since validation fails ("created_at cannot be blank"). There is nothing special with this class. Nothing is overridden. What could be the problem?
It turned out that the validation rules caused the troubles. Unexpected, since I thought all is correct. These were my rules:
public function rules() {
return [
[['id', 'name', 'created_at'], 'required'],
[['id'], 'int'],
[['name'], 'string', 'max' => 100],
[['created_at' ], 'datetime'],
];
}
created_at must not be required - that was the problem.
It is even documented:
Because attribute values will be set automatically by this behavior,
they are usually not user input and should therefore not be validated,
i.e. created_at and updated_at should not appear in the rules() method
of the model.
When $workspace->save() gets executed then the first step is the validation. And only after that step the EVENT_BEFORE_INSERT/EVENT_BEFORE_UPDATE gets triggered which causes TimestampBehaviour to populate the specified fields. And this happens only if the validation was successful! (if you var_dump you will indeed see an empty created_at.) Too late, validation has taken place already and I've got the validation error.
Recommended solution is to remove created_at from the required rule. Other approaches are also possible, of course (e.g. turn off validation or pass the properties that should be validated when save() gets called).
Add behaviour like bellow
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'create_time',
'updatedAtAttribute' => 'update_time',
'value' => new Expression('NOW()'),
],
];
}
and add it to safe records in your model class.
public function rules()
{
return array(
array('create_time,update_time', 'safe'),
);
}

Resources