I've created a set of custom validation rules in my Laravel application. I first created a validators.php
file which is in the App\Http
directory:
/**
* Require a certain number of parameters to be present.
*
* @param int $count
* @param array $parameters
* @param string $rule
* @return void
* @throws \InvalidArgumentException
*/
function requireParameterCount($count, $parameters, $rule) {
if (count($parameters) < $count):
throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters.");
endif;
}
/**
* Validate the width of an image is less than the maximum value.
*
* @param string $attribute
* @param mixed $value
* @param array $parameters
* @return bool
*/
$validator->extend('image_width_max', function ($attribute, $value, $parameters) {
requireParameterCount(1, $parameters, 'image_width_max');
list($width, $height) = getimagesize($value);
if ($width >= $parameters[0]):
return false;
endif;
return true;
});
I'm then adding including this in my AppServiceProvider.php
file (while also adding use Illuminate\Validation\Factory;
at the top of this file):
public function boot(Factory $validator) {
require_once app_path('Http/validators.php');
}
Then in my form request file, I can call the custom validation rule, like so:
$rules = [
'image' => 'required|image|image_width:50,800',
];
Then in the Laravel validation.php
file located in the resources/lang/en
directory, I'm adding another key/value to the array to display an error message if the validation returns false and fails, like so:
'image_width' => 'The :attribute width must be between :min and :max pixels.',
Everything works fine, it checks the image correctly, displays the error message if it fails, but I'm not sure how to replace :min
and :max
with the values declared in the form request file (50,800), the same way :attribute
is replaced with the forms field name. So currently it displays:
The image width must be between :min and :max pixels.
Whereas I want it to display like this
The image width must be between 50 and 800 pixels.
I've seen some replace*
functions in the master Validator.php
file (vendor/laravel/framework/src/Illumiate/Validation/)
, but I can't quite seem to figure out how to get it to work with my own custom validation rule.
I haven't used it this way but you can probably use:
$validator->replacer('image_width_max',
function ($message, $attribute, $rule, $parameters) {
return str_replace([':min', ':max'], [$parameters[0], $parameters[1]], $message);
});
Here's a solution I used:
In composer.json:
"autoload": {
"classmap": [
"app/Validators"
],
In App/Providers/AppServiceProvider.php:
public function boot()
{
$this->app->validator->resolver(
function ($translator, $data, $rules, $messages) {
return new CustomValidator($translator, $data, $rules, $messages);
});
}
In App/Validators/CustomValidator.php
namespace App\Validators;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Validator as Validator;
class CustomValidator extends Validator
{
// This is my custom validator to check unique with
public function validateUniqueWith($attribute, $value, $parameters)
{
$this->requireParameterCount(4, $parameters, 'unique_with');
$parameters = array_map('trim', $parameters);
$parameters[1] = strtolower($parameters[1] == '' ? $attribute : $parameters[1]);
list($table, $column, $withColumn, $withValue) = $parameters;
return DB::table($table)->where($column, '=', $value)->where($withColumn, '=', $withValue)->count() == 0;
}
// All you have to do is create this function changing
// 'validate' to 'replace' in the function name
protected function replaceUniqueWith($message, $attribute, $rule, $parameters)
{
return str_replace([':name'], $parameters[4], $message);
}
}
:name is replace by $parameters[4] in this replaceUniqueWith function
In App/resources/lang/en/validation.php
<?php
return [
'unique_with' => 'The :attribute has already been taken in the :name.',
];
In my controller, I call this validator like this:
$organizationId = session('organization')['id'];
$this->validate($request, [
'product_short_title' => "uniqueWith:products,short_title,
organization_id,$organizationId,
Organization",
]);
This is what it looks like in my form :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With