Similar to the confirmation
rule, I'm creating a validation rule that's based on the value of another attribute. From what I've found the only way to accomplish this is by extending the Validator class and get the value through $this->data
.
The docs say to extend the Validator and then use Validator::resolver
to register the new extension class. This works fine, but only in the case of a single resolver as it seems each subsequent defined resolver simply overrides the previous one.
How can this problem be solved? How can we define custom validators that still have access to other attributes without putting all methods in the same class...?
Thanks
//
Note: I'm asking this because I'd like to release a few validator packages, but following the reasoning above they'd just become useless if someone installs multiple packages...
I sub-classed
Illuminate\Validation\Factory
,Illuminate\Validation\ValidationServiceProvider
, andIlluminate\Validation\Validator
as (for example)MyFactory
,MyValidationServiceProvider
, andMyValidator
, respectively.MyFactory.php looked like this:
MyValidationServiceProvider.php looked like this:
MyValidator.php looked like this:
Lastly, I had to update the service provider in app.php to point to
MyValidationServiceProvider' instead of
Illuminate\Validation\ValidationServiceProvider`.The facade
Validator
now points toMyValidator
. You could even go to the extent of creating multiple factories, adding (and calling) methods toMyValidationServiceProvider
to register other validator classes to map the new factories to new IoC bindings, creating new facade classes, and adding entries to the facades in app.php to have different facades for each validator that you make.Yup, the reason it is getting overridden is the
Validator\Factory
class only stores oneresolver
. The code for the function is here:I would assume that the point of the
resolver
method is to extend the base validation class with your own. This makes sense as you could instantiate aUserRegistrationValidator
adding your own validation rules that have all the flexibility as the existing ones.One issue with this is that it can be overridden with ease, this indicates to me that you should only call the
resolver
method just before callingmake
. Although more effort, it would stop rules from different packages potentially overriding other rules and even the base ones automatically.But this does not work well for a package that only provides extra helpful rules. The simpler version to add a rule is:
This does not allow access to the input data, which is important for complex rules. The documentation example shows us this also:
But wait! What the documentation doesn't tell you is that you can add on another parameter to get the instance of
Validator
. Which I just found out myself whilst writing this answer and getting deep into the classes!So to conclude, pass an extra parameter which will be the instance of the validator being used. I suspect this will also work with a callback too.
Hope this helps, it did for me!