We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Multidimensional array validation

So it is stated in the documentation: Phalcon\Validation is an independent validation component that validates an arbitrary set of data. However I found out that there seem to be no way to validate folded arrays.

$validation = new Phalcon\Validation();

$data = ['external' => ['internal' => 1]];

$validation->add("external", new Phalcon\Validation\Validator\PresenceOf());
// How do I validate internal?
$validation->add('???', new Phalcon\Validation\Validator\PresenceOf());

$errors = $validation->validate($data);

I've looked into sources, where it ends with zend_symtable_find, which as far as I understand doesn't go deep into an array (which is absolutely logical by itself).



2.1k

I'm not sure if there's currently validator for sub array. However, --one of my favorite feature of phalcon-- we can customize it.

For example, you can create custom presence validator like:

use Phalcon\Validation\Validator,
    Phalcon\Validation\ValidatorInterface,
    Phalcon\Validation\Message;

class MyPresenceValidator extends Validator implements ValidatorInterface
{

    /**
     * Executes the validation
     *
     * @param \Phalcon\Validation $validator
     * @param string $attribute
     * @return boolean
     */
    public function validate($validator, $attribute)
    {
        $array = explode(".", $attribute);
        if (count($array) > 0){
            $value = $validator->getValue($array[0]);
            for($i = 1; $i < count($array); $i++){
                if (!isset($value[$array[$i]])){
                    $validator->appendMessage(new Message(str_replace(":field", $attribute, $validator->getDefaultMessage("PresenceOf")), $attribute));
                    return false;
                }
                $value = $value[$array[$i]];
            }
            if ($value !== null){
                return true;
            }
        }
        return false;
    }
}

and use it on the validation:

        $validation = new \Phalcon\Validation();

        $data = ['external' => ['internal' => ['deeper' => 1]]];

        $validation->add("external", new \Phalcon\Validation\Validator\PresenceOf());
        $validation->add('external.internal', new MyPresenceValidator());
        $validation->add('external.internal.deeper', new MyPresenceValidator());
        $validation->add('external.internal.crazystuff', new MyPresenceValidator());

        $errors = $validation->validate($data);

        echo "errors:";
        foreach($errors as $error){
            /* @var $error Message */
            print_r($error->getMessage());
       }

Well, it's a quick and dirty way to do it, but I hope you get the point.

Cheers,



12.1k

Thank you for an extensive reply. You are right, there is plenty possibilities for workaround in this case. However I hope someday we can have something really powerful for arbitrary data validation. In particular, my attention was attracted by Symfony/Config component, and specifically it's Definition part, where you can define array structure and constraints and validate it.

https://symfony.com/doc/current/components/config/definition.html

I am using new validation classes for subarrays and use them in afterValidation method.