Respect / Validation

The most awesome validation engine ever created for PHP
https://respect-validation.readthedocs.io
MIT License
5.76k stars 774 forks source link

2.2.3: Extended AllOf + Nesting > Call to undefined method Respect\Validation\Exceptions\ValidationException::addChildren() #1354

Closed TCB13 closed 1 year ago

TCB13 commented 3 years ago

Hello,

I was trying to create a validator that is based on existing validators. The idea is to allow the user to input any MySQL/MariaDB valid form of a boolean that can be a real PHP boolean (later on converted to an int by the driver) a int (0 or 1) or a string containing "0" or "1":

class SQLBool extends Rules\AllOf
{
    public function __construct()
    {
        parent::__construct(
            new Rules\AnyOf(
                new Rules\BoolType(),
                new Rules\AllOf(
                    new Rules\IntType(),
                    new Rules\In([1,0])
                ),
                new Rules\AllOf(
                    new Rules\StringType(),
                    new Rules\In(["1","0"])
                ),
            ),
        );
    }
}

Using ->validate() on that works as expected:

$v = new v();
$v->key("public", new SQLBool());
var_dump("bool true", $v->validate(["public" => true]));
var_dump("bool false", $v->validate(["public" => false]));
var_dump("int 1", $v->validate(["public" => 1]));
var_dump("int 0", $v->validate(["public" => 0]));
var_dump("string 1", $v->validate(["public" => "1"]));
var_dump("string 0", $v->validate(["public" => "0"]));
var_dump("string abcd", $v->validate(["public" => "abcd"]));

// Results:
string(9) "bool true"
bool(true)
string(10) "bool false"
bool(true)
string(5) "int 1"
bool(true)
string(5) "int 0"
bool(true)
string(8) "string 1"
bool(true)
string(8) "string 0"
bool(true)
string(11) "string abcd"
bool(false)

Now, ->assert() seems to be broken if the data is invalid:

try {
    $v->assert(["public" => "abcd"]);
} catch (NestedValidationException $exception) {
    var_dump($exception);
}

// Result:

Fatal error: Uncaught Error: Call to undefined method Respect\Validation\Exceptions\ValidationException::addChildren() in project\vendor\respect\validation\library\Rules\AllOf.php:42
Stack trace:
#0 project\vendor\respect\validation\library\Rules\AbstractRelated.php(115): Respect\Validation\Rules\AllOf->assert('abcd')
#1 project\vendor\respect\validation\library\Rules\AbstractComposite.php(102): Respect\Validation\Rules\AbstractRelated->assert(Array)
#2 [internal function]: Respect\Validation\Rules\AbstractComposite->Respect\Validation\Rules\{closure}(Object(Respect\Validation\Rules\Key))
#3 project\vendor\respect\validation\library\Rules\AbstractComposite.php(111): array_map(Object(Closure), Array)
#4 project\vendor\respect\validation\library\Rules\AllOf.php(31): Respect\Validation\Rules\AbstractComp in project\vendor\respect\validation\library\Rules\AllOf.php on line 42

Is this expected / am I doing it the wrong way or is it a bug?

Side note: I was expecting to be able to extend the AnyOf validator for this but since it is a final class I was forced to go around with AllOff... Maybe this isn't necessary?

Respect/Validation version: 2.2.3 PHP: 7.4.1

Thank you!

alganet commented 2 years ago

Did you created a SQLBoolException extending AllOfException? Each rule absolutely needs is counterpart exception class in order to AbstractRule::reportError to work.

Check out the guide for creating custom rules: https://respect-validation.readthedocs.io/en/latest/custom-rules/

alganet commented 1 year ago

Closed due to inactivity after response. Feel free to reopen if this is still an issue!