Custom Rules#

ReqShield provides two ways to add your own validation logic: 1. Simple (inline) with ``Callback``: For quick, one-off rules. 2. Advanced (reusable) with ``Rule``: For complex, reusable rules.

1. Simple Callbacks#

For simple, single-use rules, pass Infocyph\ReqShield\Rules\Callback in your rule list.

The Callback constructor accepts: * callback: callable signature fn (mixed $value, string $field, array $data): bool. * cost (optional): An integer cost. Keep it low (e.g., 20) unless it’s a slow operation. * message (optional): A custom error message.

use Infocyph\ReqShield\Rules\Callback;
use Infocyph\ReqShield\Validator;

$validator = Validator::make([
    'code' => [
        'required',
        // Example: Must be a specific format
        new Callback(
            callback: fn ($value, $field, $data) => preg_match('/^[A-Z]{3}-\d{4}$/', $value),
            cost: 20,
            message: 'Code must be in format ABC-1234'
        ),
    ],
    'even_number' => [
        'required',
        'integer',
        // Example: Must be an even number
        new Callback(
            callback: fn ($value, $field, $data) => $value % 2 === 0,
            cost: 5,
            message: 'Number must be even'
        ),
    ],
]);

$result = $validator->validate([
    'code' => 'ABC-1234',
    'even_number' => 42,
]);
// $result->passes() will be true

2. Reusable Rule Classes#

For reusable logic, implement Infocyph\ReqShield\Contracts\Rule (or extend BaseRule).

<?php
namespace MyApp\Rules;

use Infocyph\ReqShield\Contracts\Rule;
use Infocyph\ReqShield\Rules\BaseRule; // (Optional) for helper methods

class IsEven extends BaseRule implements Rule
{
    /**
     * Set the performance cost.
     * 1-49 (cheap), 50-99 (medium), 100+ (expensive)
     */
    public function cost(): int {
        return 5; // This is a very cheap check
    }

    /**
     * The validation logic.
     * Return true if it passes, false if it fails.
     */
    public function passes(mixed $value, string $field, array $data): bool {
        return is_numeric($value) && $value % 2 === 0;
    }

    /**
     * The error message if validation fails.
     */
    public function message(string $field): string {
        return "The {$field} field must be an even number.";
    }
}

Using Your Reusable Rule#

You can use your new rule class just like the Callback rule.

use MyApp\Rules\IsEven;

$validator = Validator::make([
    'even_number' => ['required', 'integer', new IsEven()],
]);

$result = $validator->validate(['even_number' => 42]); // Passes
$result2 = $validator->validate(['even_number' => 7]); // Fails

Register a Custom Rule Name#

If you want to use a custom string token (for example even), register it on the validator instance:

use App\Rules\IsEven;
use Infocyph\ReqShield\Validator;

$validator = Validator::make([
    'number' => 'required|even',
])->registerRule('even', IsEven::class);

$result = $validator->validate(['number' => 8]);