paolo@bimodesign.com | +34 608 61 64 10

Framework

        

Symfony2, using validation constraint "all" and custom choice function

I've started developing with Silex, a Symphony2 microframework, from few mounths and I'm using the validation constraints for JSON input data. The constraints covered the validation of a lot of objects and in this post I'll describe a complex case, where I'll use the ALL constraint.
The JSON complex structure is

{
    "establishment": 1,
    "typeId": 1,
    "configuration":{
        "couponValue": 15.60,
        "discountOrMoney": 1,
        "sameCouponsForAll": 0,
	"target": 15,
        "filterCoupons": {
            "33": [{
                	"from": 1,
                	"to": 7,
                	"assign": 5
            	},
            	{
                	"from": 8,
                	"to": 15,
                	"assign": 10
            	}],
            "34": [{
            	    "from": 1,
             	   "to": 7,
             	   "assign": 7
            	},
            	{
             	   "from": 8,
             	   "to": 15,
            	    "assign": 12
            }]
        },
        "couponRedeemedDate": "2013-12-01",
        "minimunPurchase": 10,
        "redeemedByBooking": 0,
        "onlyOneCouponRedeemed": 1,
        "couponType": "user"
    },
    "status": 1,
    "deliveryFrom": "2013-08-01",
    "deliveryTo": "2013-10-01",
etc..
etc..

I have to apply this validation rules to "filterCoupons" structure
1. "filterCoupons" is an optional element (I don't need checking its dependency)
2. At least a element/array has to exist. (The array id will be numeric or string, then I will not validate it)
3. Each element with numeric or string id, has to contain at least an element/array
4. The fields "From" and "to", that are into the last array (3.), are optional, but, if they will be into the first array occurrence, so the others arrays will have them (Edit: This is more complex validation, so I'll analyze it for a next post)
5. The field "assign" is mandatory

In order to validate all the elements of the array of the arrays, I have to use the all constraint, duplicating it, in this way

Note: I divide the PHP code in two parts, cause I use the lower validation also for another part of that complex JSON.
That's the simple code:
The common lower array validation

$couponsData = new Assert\Collection(
    array(
        'fields' => array(
            'from' => new Assert\Optional(
                array(
                    new Assert\NotBlank(),
                    new Assert\Type(array('type' => 'int'))
                )
            ),
            'to' => new Assert\Optional(
                array(
                    new Assert\NotBlank(),
                    new Assert\Type(array('type' => 'int'))
                )
            ),
            'assign' => array(
                new Assert\NotBlank(),
                new Assert\Type(array('type' => 'int'))
            ),
        )
    )
);

The main validation structure of filterCoupons

'filterCoupons' => new Assert\Optional(
    array(
        new Assert\All(
            array(
                new Assert\All(
                    $couponsData
                )      
            ) 
        )
    )
), 


In case of an element of the lower array, for example "assign", is a list of string mandatory values, for example "php, mysql, apache, linux", then I'll use the choice constraint, in this way
Adding this simple function
public static function setLampAssign()
{
    return array('php', 'mysql', 'apache', 'linux');
}  

Then I change the lower validation in this way (Adding the optional too, in order to show the complete case)

$couponsData = new Assert\Collection(
    array(
        'fields' => array(
            'from' => new Assert\Optional(
                array(
                    new Assert\NotBlank(),
                    new Assert\Type(array('type' => 'int'))
                )
            ),
            'to' => new Assert\Optional(
                array(
                    new Assert\NotBlank(),
                    new Assert\Type(array('type' => 'int'))
                )
            ),
            'assign' => new Assert\Optional(
                array(
                    new Assert\NotBlank(),
                    new Assert\Type(array('type' => 'string')),
                    new Assert\Choice(
                        array(
                            'choices' => $this->setLampAssign(),
                            'message' => 'The value {{ value }} is not a valid assign content.',
                        )
                    )
                )
            ),
        )
    )
);