How to do the validation in the nested array

4 years ago

lobzang
Member | 6
+
0
-
<?php
private $requiredParameters = array(
        'customer' => [
            'name' => 'string',
            'billingAddress' => 'string',
            'email' => 'email'
        ],
        'items' => [

            'bookingNumber' => 'string',
            'currency' => 'string',
            'taxPercent' => 'numeric',
            'sellingPrice' => 'numeric',
            'hotelName' => 'string',
            'checkInDate' => 'date',
            'checkOutDate' => 'date',
            'discount' =>'numeric'

        ]
    );

    public function validate(array $parameters)
    {
        foreach ($this->requiredParameters as $key => $item) {
            foreach ($item as $itemName => $dataType) {
                if ( ! isset($parameters[$key][$itemName])) {
                    throw new InvalidArgumentException('Missing value : ' . $itemName);
                }
                $value = $parameters[$key][$itemName];
                $this->{'validate' . ucfirst($dataType)}($value);
            }
        }
        return false;
    }
?>

I am trying to do the validation for the array given above. The problem is that the validation works for the customer when it reached items array it fail to do the validation. help me how to do the validation dynamic for the array.

Last edited by lobzang (2015-07-08 07:13)

4 years ago

Felix
Nette Core | 956
+
0
-

I think you have to validate each group separate.

Or make validation for each key of top-level oft the array.

public function validate(array $params) {
    foreach ($params as $key => $param) {
        if (is_array($param)) {
            $this->{'validate' . ucfirst($key)}($param);
        }
    }
}

protected function validateCustomer(array $params) {
//..
}

protected function validateItems(array $params) {
//..
}

For inspiration, CompilerExtension::validateConfig.

4 years ago

Nivin17
Member | 2
+
0
-

At this time, the Validator class isn't meant to iterate over array data. While it can traverse through a nested array to find a specific value, it expects that value to be a single (typically string) value.

The way I see it, you have a few options:

1: Create rules with the array key in the field name.

Basically essentially what you're doing already, except you'd need to figure out exactly how many values your [‘stuff’][‘item’] array has. I did something like this with good results:

$data = [
‘stuff’ ⇒ [
‘item’ ⇒ [
[‘title’ ⇒ ‘flying_lotus’],
[‘title’ ⇒ ‘various_cheeses’],
[‘title’ ⇒ ''],
[‘title’ ⇒ ‘welsh_cats’],
]
 ]
];

$rules = [];

for ($i = 0, $c = count($data[‘stuff’][‘item’]); $i < $c; $i++)
{
$rules[“stuff.item.{$i}.title”] = ‘required’;
}

$v = Validator::make($data, $rules);

var_dump($v->passes());
2: Create a custom validation method.

This will allow you to create your own rule, where you can expect an array value and iterate it over as necessary.

This method has its caveats, in that A) you won't have specific value error messages, since it'll error for the entire array (such as if you pass stuff.item as the value to check), and B) you'll need to check all of your array's possible values in your custom function (I'm assuming you'll have more than just title to validate).

You can create the validation method by using the Validator::extend() or by fully extending the class somewhere else. Java training in chennai | Android training in chennai

3: Extend the Validator class and replace/parent the rules in question to accept arrays.

Create your own extended Validator class, and either implement custom rules, or rename existing ones, enabling those rules to accept an array value if one happens along. This has some similar caveats to the #2 custom rule option, but may be the “best practice” if you intend on validating iterated arrays often.