mirror of
https://github.com/Respect/Validation.git
synced 2026-03-17 07:45:45 +01:00
When nested-structural validation fails, it's challenging to identify which rule failed from the main exception message. A great example is the `Issue796Test.php` file. The exception message says: host must be a string But you're left unsure whether it's the `host` key from the `mysql` key or the `postgresql` key. This commit changes that behaviour by introducing the concept of "Path." The `path` represents the path that a rule has taken, and we can use it in structural rules to identify the path of an array or object. Here's what it looks like before and after: ```diff -host must be a string +`.mysql.host` must be a string ``` Because paths are a specific concept, I added a dot (`.`) at the beginning of all paths when displaying them. I was inspired by the `jq` syntax. I also added backticks around paths to distinguish them from any other value. I didn't manage to fix a test, and I skipped it instead of fixing it because I want to make changes in how we display error messages as arrays, and it will be easier to fix it then.
56 lines
1.2 KiB
PHP
56 lines
1.2 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Respect\Validation\Rules;
|
|
|
|
use ArrayAccess;
|
|
use Attribute;
|
|
use Respect\Validation\Message\Template;
|
|
use Respect\Validation\Result;
|
|
use Respect\Validation\Rules\Core\KeyRelated;
|
|
use Respect\Validation\Rules\Core\Standard;
|
|
|
|
use function array_key_exists;
|
|
use function is_array;
|
|
|
|
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
|
|
#[Template(
|
|
'{{name}} must be present',
|
|
'{{name}} must not be present',
|
|
)]
|
|
final class KeyExists extends Standard implements KeyRelated
|
|
{
|
|
public function __construct(
|
|
private readonly int|string $key
|
|
) {
|
|
}
|
|
|
|
public function getKey(): int|string
|
|
{
|
|
return $this->key;
|
|
}
|
|
|
|
public function evaluate(mixed $input): Result
|
|
{
|
|
return new Result($this->hasKey($input), $input, $this, path: $this->key);
|
|
}
|
|
|
|
private function hasKey(mixed $input): bool
|
|
{
|
|
if (is_array($input)) {
|
|
return array_key_exists($this->key, $input);
|
|
}
|
|
|
|
if ($input instanceof ArrayAccess) {
|
|
return $input->offsetExists($this->key);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|