Pre-processing
Before you can use a custom validation rule, you must define the namespace prefix for the custom validation rule
ValidateConfig::instance()->setRulesPath('W7\\App\\Model\\Validate\\Rules\\');
It is recommended to define the validate-related settings in Provider
.
Priority
The validator's Built-in Rules is greater than that of the extended rules, so care needs to be taken that the rule names are not consistent.
Extending global rules
Global rules refer to rules that can be used in all validators
Using rule objects
There are many useful validation rules within the validator; custom rules are also supported。 One way to register a custom validation rule is to create a new rule and inherit from W7\Validate\Support\Rule\BaseRule
. The new rule is stored in the directory you have set up.
Once the rule is created, we can define its behavior. The passes
method takes the attribute value and name and returns true
or false
depending on whether the attribute value matches the rule. The message
attribute is the validation error message used in case of validation failure, which can be overridden by the message
defined in the validator.
ImplicitRule
If you would like a rule object to run when an attribute is empty, you should implement the Itwmw\Validation\Support\Interfaces\ImplicitRule
interface. This interface serves as a "marker interface" for the validator; therefore, it does not contain any methods you need to implement.
namespace W7\App\Model\Validate\Rules;
class Chs extends BaseRule
{
/**
* Default error message
* @var string
*/
protected $message = 'The value of :attribute can only have Chinese';
/**
* Determine if the validation rules pass。
*
* @param mixed $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value): bool
{
return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value);
}
}
Once the rule object has been defined, you can pass an instance of the rule object to the validator by passing it along with other validation rules:
protected $rule = [
'title' => 'required|chs',
];
Rule object error message formatting support:Formatting error messages
The rules also support standalone calls to use
Chs::make()->check("name");
Validation returns true
, failure returns false
extend
Use the extend
static method in Validate
to register global rules. Let's use this method in the validate to register a custom validation rule.
Validate::extend('chs', function ($attribute, $value, $parameters, $validator) {
return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value);
}, 'The value of :attribute can only have Chinese');
The custom validation closure takes four parameters: the name of the attribute to be validated $attribute
, the value of the attribute $value
, an array of parameters to be passed into the validation rule $parameters
, and a Validator
instance.
In addition to using closures, you can also pass in classes and methods to the extend
method:
Validate::extend("check_admin","permissionValidate@checkAdmin");
Note
If your method is a static method, you can also pass in an array of [full class name, method name], if the method name is not passed, the default method name is validate
.
replacer
If you need to define an error message, you can fill in the third parameter of extend
, or define it via the replacer
method
The replacer
method accepts two parameters ruleName
and a closure parameter, and the closure accepts four parameters: error message $message
, the name of the attribute being validated $attribute
, the name of the current rule $rule
, an array of parameters to be passed into the validation rule $parameters
Validate::replacer("check_admin",function($message,$attribute,$rule,$parameters){
return "Customized error messages"
});
In addition to using closures, passing in classes and methods to the replacer
method is also supported
Validate::replacer("check_admin","permissionValidate@checkAdminMessage");
Note
Passing in classes and methods requires specifying the method as a public
type, if it's a class, you need to pass in the full namespace, does not support array passing, such as the method name is not passed, the default method name replace
.
Custom messages that can override default rules. To define error messages for custom methods, be sure to define the error rule extend
first, then the error message replacer
.
Use in the same way as with rule objects
protected $rule = [
'title' => 'required|chs|check_admin',
];
extendImplicit
By default, when an attribute being validated is not present or contains an empty string, normal validation rules, including custom extensions, are not run. For example, the unique
rule will not be run against an empty string:
$rules = ['name' => 'unique:users,name'];
$input = ['name' => ''];
// Validate passed
For a rule to run even when an attribute is empty, the rule must imply that the attribute is required. To create such an "implicit" extension, use the extendImplicit()
method in Validate
:
Validate::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
extendDependent
If we want to define a custom extension to validate the array, we will find that neither extend
nor extendImplicit
will resolve *
, so we need to use the extendDependent
method in Validate
:
Validate::extendDependent('contains', function ($attribute, $value, $parameters, $validator) {
// The $parameters passed from the validator below is ['*.provider'], when we imply that this
// custom rule is dependent the validator tends to replace the asterisks with the current
// indices as per the original attribute we're validating, so *.provider will be replaced
// with 0.provider, now we can use array_get() to get the value of the other field.
// So this custom rule validates that the attribute value contains the value of the other given attribute
return str_contains($value,Arr::get($validator->getData(),$parameters[0]));
});
$v = new Validate();
$v->setRules([
'*.email' => 'contains:*.provider'
])->check([
[
'email' => '995645888@qq.com', 'provider' => 'qq.com'
]
]);
Custom rules within the validator
Using class methods
Custom rules also support the direct use of methods under the current validator class, the rule is rule
+ rule name, e.g. ruleCheckLogin
Note
The checkLogin
here and other methods registered under the current validator must not duplicate the rule name, otherwise it will overwrite
The Custom Rule method takes four parameters: The name of the attribute to be validated $attribute
, the value of the attribute $value
, an array of parameters to be passed into the validation rule $parameters
, and a Validator
instance.
class LoginValidate extends Validate
{
protected $rule = [
'user' => 'required|alphaNum|checkLogin'
];
protected $message = [
'user.checkLogin' => 'Login failure'
];
public function ruleCheckLogin($attribute, $value, $parameters, $validator): bool
{
return 'admin' === $value;
}
}
You can also set error messages for class method rules with the $ruleMessage
parameter
class Test extends Validate
{
protected $ruleMessage = [
'chs' => 'The value of :attribute can only have Chinese'
];
protected function ruleChs($attribute, $value, $parameters, $validator): bool
{
return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value);
}
}
Regular Expression Rule
Supports direct use of regular validation, e.g:
'id' => 'regex:/^\d+$/',
If your regular expression contains the |
symbol, it must be defined in an array.
'id' => ['regex:/^\d+$/']
You can also implement a predefined regular expression and call it directly, for example, by defining the regex
property in the validator class and then using regex:
+ regular name
in the rule
class Test extends \W7\Validate\Validate
{
protected $regex = [
'number' => '/^\d+$/'
];
protected $rule = [
'id' => 'regex:number'
];
}
Defining the Dependent Validator
Use the extendDependentRule
method in the Validate
class to have the same effect as extendDependent, but only with this validator
class LoginValidate extends Validate
{
public function __construct()
{
$this->extendDependentRule('contains', function ($attribute, $value, $parameters, $validator) {
return str_contains($value, Arr::get($validator->getData(), $parameters[0]));
});
}
}
Defining the Implicit Validator
Use the extendImplicitRule
method in the Validate
class to have the same effect as extendImplicit, but only with this validator
class LoginValidate extends Validate
{
public function __construct()
{
$this->extendImplicitRule('isEmpty', function ($attribute, $value, $parameters, $validator) {
return empty($value);
});
}
}
Custom rule incoming parameters
Custom rules, like other rules, also support passing in parameters, similar to max:100
, in:0,1,2
, which will be passed into the constructor of the custom rule class in order. as follows:
class Length extends BaseRule
{
protected $message = 'The length of :attribute does not meet the requirement';
protected $size;
public function __construct(int $size)
{
$this->size = $size;
}
public function passes($attribute, $value): bool
{
return strlen($value) === $this->size;
}
}