Skip to content

Instantly share code, notes, and snippets.

@LegitDongo
Last active December 1, 2022 19:35
Show Gist options
  • Save LegitDongo/2626ce323b8396349b30b5c4a544bca6 to your computer and use it in GitHub Desktop.
Save LegitDongo/2626ce323b8396349b30b5c4a544bca6 to your computer and use it in GitHub Desktop.
A validation rule for Laravel that sets min/max boundries based on the mysql column type. Excludes variable-length column types.
<?php
/**
* this file is app/Providers/AppServiceProvider@boot
*
* adds the global "col" key for validators
* possible values are as follows:
* string types:
* `varchar`, `tinytext`, `text`, `mediumtext`, `longtext`
* NOTE: `varchar` assumes the default for Laravel, 255; don't use this if you use a specific column size
*
* number types (non-explicit assumes it's signed):
* `bit`, `bool`, `boolean`,
* `tinyint`, `signed_tinyint`, `unsigned_tinyint`,
* `smallint`, `signed_smallint`, `unsigned_smallint`,
* `mediumint`, `signed_mediumint`, `unsigned_mediumint`,
* `int`, `integer`, `signed_int`, `signed_integer`, `unsigned_int`, `unsigned_integer`,
* `bigint`, `signed_bigint`, `unsigned_bigint`
*
* usage with example; ripped out of https://laravel.com/docs/9.x/validation#quick-writing-the-validation-logic
* $validated = $request->validate([
* 'title' => 'required|unique:posts|col:tinytext',
* 'body' => 'required|col:text',
* ]);
*/
Validator::extend('col', function ($attribute, $value, $parameters, $validator) {
/**
* @var string $attribute
* @var string $value
* @var string[] $parameters
* @var \Illuminate\Validation\Validator $validator
*/
if (count($parameters) < 1) {
throw new \InvalidArgumentException("Validation rule col requires at least 1 parameters.");
}
$textSizes = [
'varchar' => 255, // assumes that the VARCHAR field accepted the default size, which is max pre MySQL 5.0.3
'tinytext' => 255,
'text' => 65535,
'mediumtext' => 16777215,
'longtext' => 4294967295
];
$numberSizes = [
'bit' => [0, 1],
'bool' => [0, 1],
'boolean' => [0, 1],
'tinyint' => [-128, 127],
'signed_tinyint' => [-128, 127],
'unsigned_tinyint' => [0, 255],
'smallint' => [-8388608, 8388607],
'signed_smallint' => [-8388608, 8388607],
'unsigned_smallint' => [0, 65535],
'mediumint' => [-8388608, 8388607],
'signed_mediumint' => [-8388608, 8388607],
'unsigned_mediumint' => [0, 16777215],
'int' => [-2147483648, 2147483647],
'signed_int' => [-2147483648, 2147483647],
'unsigned_int' => [0, 4294967295],
'integer' => [-2147483648, 2147483647],
'signed_integer' => [-2147483648, 2147483647],
'unsigned_integer' => [0, 4294967295],
'bigint' => ['-9223372036854775808', '9223372036854775807'],
'signed_bigint' => ['-9223372036854775808', '9223372036854775807'],
'unsigned_bigint' => [0, '18446744073709551615'],
];
if (!isset($textSizes[$parameters[0]]) && !isset($numberSizes[$parameters[0]])) {
throw new \InvalidArgumentException(
'Validation rule col requires a valid mysql column type on field ' . $attribute
);
}
$min = $numberSizes[$parameters[0]][0] ?? 0;
$max = $numberSizes[$parameters[0]][1] ?? $textSizes[$parameters[0]];
$validator->setCustomMessages([
'col' => "The :attribute field requires the value to be between $min and $max"
. (isset($textSizes[$parameters[0]]) ? ' characters long' : '')
]);
if (isset($textSizes[$parameters[0]])) {
return mb_strlen($value) <= $textSizes[$parameters[0]];
}
return $min <= $value && $max >= $value;
});
@LegitDongo
Copy link
Author

Instead of having a giant closure in your AppServiceProvider, you can also abstract it to a class and call it like the following:
Validator::extend('col', '\App\Rules\MysqlColumnLengthRule@validate')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment