Milk Admin

Model Validation Rules

This page documents the server-side validation rules defined in a Model configure() method with the RuleBuilder. These rules are evaluated by AbstractModel::validate() and are used by FormBuilder when saving records.

Note: Many rules also map to HTML attributes via formParams() (frontend validation), but validation always runs on the backend.

Required vs Nullable

  • required() enforces that a value is present during validation.
  • nullable(false) sets the column as NOT NULL in the schema; validation still needs required() if you want to block empty values at runtime.
  • Default is nullable(true).

$rule->string('name', 100)
    ->required()
    ->nullable(false); // not nullable in DB

$rule->string('nickname', 50)
    ->nullable(); // can be empty
    

Numeric Rules

  • min($value) / max($value): numeric range validation
  • step($value): numeric step validation

$rule->int('priority')
    ->min(0)
    ->max(100)
    ->step(5);
    

Compare With Another Field (backend only)

You can pass a field name to min() or max() to compare values on the backend.


$rule->int('min_members')->max('max_members');
$rule->int('max_members')->min('min_members');
    

String / Text Rules

  • min($value) / max($value): minimum/maximum length for string/text
  • string('field', 100): sets max length (100)
  • formParams(['pattern' => '...']): regex validation (also applied server-side)

$rule->string('code', 20)
    ->min(5)
    ->formParams(['pattern' => '^[A-Z0-9]+$']);
    

Date / Time Rules

  • min() / max() accept date/time strings or another field name
  • Use formats like YYYY-MM-DD and HH:MM

$rule->date('start_date')->max('end_date');
$rule->date('end_date')->min('start_date');

$rule->time('start_time')->max('end_time');
    

Enum / List

For enum and list fields, validation checks that the value is in the allowed options.


$rule->list('status')
    ->options(['new' => 'New', 'active' => 'Active', 'archived' => 'Archived']);
    

Custom Validation

Use a custom validation method via the #[Validate('field_name')] attribute for backend rules.


use App\Attributes\Validate;

#[Validate('code')]
protected function validateCode(object $row): ?string
{
    if (!preg_match('/^[A-Z0-9]+$/', $row->code ?? '')) {
        return 'Invalid code';
    }
    return null;
}
    

Custom Validation (Frontend JS)

For custom client-side validation, listen to the fieldValidation event and use setCustomValidity(). This is optional and always in addition to backend validation.

document.addEventListener('updateContainer', function() {
    const codeField = document.querySelector('[name="code"]');
    if (!codeField) return;

    codeField.addEventListener('fieldValidation', function() {
        if (!/^[A-Z0-9]+$/.test(codeField.value)) {
            codeField.setCustomValidity('Invalid code');
        } else {
            codeField.setCustomValidity('');
        }
    });
});

For full examples and event details, see Form Validation with FormBuilder.

Loading...