How to use custom Laravel ValidationRule
rules in Statamic
Statamic has great support for Laravel’s baked-in validation rules – like required, min, max and so on, and even support for Illuminate\Contracts\Validation\Rule
rules. However, with Laravel 10, this Rule contract has been marked as deprecated, and to use Illuminate\Contracts\Validation\ValidationRule
instead.
However, Statamic did not have support for the ValidationRule
approach – and the previous Rule
approach was a little limiting.
So I got tinkering with a little PR to add this to Statamic, and as of Statamic 4.51.0, you’re able to use your ValidationRule
rules within Statamic.
Given the differences between Rule
and ValidationRule
, a slightly different syntax would be needed to offer the same level of functionality: and my original PR had a bit of a clunky syntax for hooking everything in to a ValidationRule
. Thankfully the awesome Jason at Statamic reworked by weird syntax in to one that is much more fluent, intuitive and elegant.
With a ValidationRule
, you’ll have a single validate
method where you’ll receive:
the field’s handle as
$attribute
,the field’s value as
$value
, andthe
$fail
callback
You can perform whatever validation checks you need, and if validation fails, call the $fail
closure, and pass your validation message – which can even support translations which is great for internationalisation support for addon development.
1<?php 2 3namespace App\Rules; 4 5use Closure; 6use Illuminate\Contracts\Validation\ValidationRule; 7 8class MyValidationRule implements ValidationRule 9{10 public function validate(string $attribute, mixed $value, Closure $fail): void11 {12 // do something to give yourself validation13 $failedValidation = true; // let's just hard wire this14 15 if ($failedValidation) {16 $fail('The message to appear in the CP.');17 }18 }19}
Using a ValidationRule
in Statamic is as simple as adding them to the Rules input like you would any other rule within the Statamic CP.
The message passed to $fail
is what will appear within the Statamic CP as a validation message.
It is also possible to pass input parameters to your ValidationRule
. This can be really helpful if your rule has a configurable parameter used for testing. Let’s say you have a rule that needs to calculate whether your field (such as a Grid or Replicator) has values that add up to a specific number – like a number of rows that need to add up to 100.
You could write a rule that does this – but you could also write a more generic rule that allows the exact sum to be configurable - maybe you need an exact sum of 100 somewhere, but only 6 somewhere else. This approach means you can write one rule that can be used in both places. Here’s a quick example:
1<?php 2 3namespace App\Rules; 4 5use Closure; 6use Illuminate\Contracts\Validation\ValidationRule; 7 8class ExactSum implements ValidationRule 9{10 public function __construct(protected $exactSum = 50)11 {12 }13 14 public function validate(string $attribute, mixed $value, Closure $fail): void15 {16 $sum = 0;17 18 // do whatever you need with $value to perform your validation19 20 if ($sum != $this->exactSum) {21 $fail('Your values must add up to '.$this->exactSum.'.');22 }23 }24}
You can then pass this $exactSum with your Rule configuration within Statamic:
And if you’re wanting to use named parameters, those will work too:
And of course, if you’re a YAML fan, you can also edit your Blueprint by hand – just remember to escape your quotes if using parameters.
1validate:2 - 'new App\Rules\ExactSum(exactSum: 6)'
It is great to see Statamic up and running with Laravel’s ValidationRule
approach – and can help ensure new projects aren’t using the deprecated Illuminate\Contracts\Validation\Rule
too.
Hero image credit: Markus Winkler (Source)