Skip to content

Using Laravel rules with custom validation rules #55702

@blue32a

Description

@blue32a

Laravel Version

12.13.0

PHP Version

8.4.7

Database Driver & Version

No response

Description

Use Laravel rules with custom validation rules.

However, nested fields do not behave as expected. Nested fields are considered not verifiable.

Is this usage appropriate?

Steps To Reproduce

Custom Validation Rules

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Validator;

class ExampleRule implements ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param  \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $validator = Validator::make(
            [$attribute => $value],
            [$attribute => ['date_format:Y/m/d']],
        );

        if ($validator->fails()) {
            $fail('error');
        }
    }
}

Tests

namespace Tests\Unit\Rules;

use App\Rules\ExampleRule;
use Illuminate\Support\Facades\Validator;
use Tests\TestCase;

class ExampleRuleTest extends TestCase
{
    public function test_non_unnested_fields_behave_as_expected(): void
    {
        $validator = Validator::make(
            ['field' => '2025-05-01'], // Value that do not pass validation
            ['field' => [new ExampleRule()],
        ]);

        $this->assertSame(true, $validator->fails()); // OK
    }

    public function test_nested_fields_do_not_behave_as_expected(): void
    {
        $validator = Validator::make(
            ['field' => ['foo' => '2025-05-01']], // Value that do not pass validation
            ['field.foo' => [new ExampleRule()]],
        );

        $this->assertSame(true, $validator->fails()); // NG
    }
}

Dump

  • Illuminate\Validation\Validator::isValidatable()
    • Illuminate\Validation\Validator::presentOrRuleIsImplicit()
      • Illuminate\Validation\Concerns\ValidatesAttributes::validatePresent()
trait ValidatesAttributes
{
    public function validatePresent($attribute, $value)
    {
        dump([$this->data, $attribute, $value]);
        return Arr::has($this->data, $attribute);
    }
}
array:3 [
  0 => array:1 [
    "field" => array:1 [
      "foo" => "2025-05-01"
    ]
  ]
  1 => "field.foo"
  2 => "2025-05-01"
] // vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php:1854
array:3 [
  0 => array:1 [
    "field__dot__9tDDcjCZCvvl01xyfoo" => "2025-05-01"
  ]
  1 => "field.foo"
  2 => null
] // vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php:1854

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions