Skip to content
Jan 21 / John Wyles

A Tailored Approach to Object Validation

I was thinking some on object validation this afternoon and found out quickly that I wanted my cake and the ability to eat it to. Namely that I wanted to be able to statically validate values for a given attribute and also contextually validate values in PHP’s magic setter. Statically validating values for attributes was a requirement as often instantiation of the object came with significant overhead (e.g. fetching from Memcache, trip to the database, etc.) so accessing its validators statically could be used to validate the setup of the object prior to its creation. Not to mention the bulk static validation operations could be run for a digest of object attributes, say, in a flat CSV file for instance. Here are the set of class I came up with:

/**
 * Generic validation (e.g. code generated) would go here
 */
abstract class Foo_Abstract_Autogenerated
{
    public static function auto_validate_bar($bar)
    {
        $validator = new Validator_Integer_Between(1, 100);
        if ($validator->valid($bar)) {
            return true;
        }

        return false;
    }
}

/**
 * Custom validation (e.g. business logic / interdependencies ) would go here
 */
abstract class Foo_Abstract extends Foo_Abstract_Autogenerated
{
    public function validate_bar($bar)
    {
        if (in_array($bar, $this->_bannedBarValues)) {
            return false;
        }

        return true;
    }
}

class Foo extends Foo_Abstract
{
    protected $_bannedBarValues = array(1, 2, 3);

    public function valide($fieldName, $value)
    {
        if (method_exists($this, 'validate_' . $fieldName)) {
            $returnValue = call_user_func_array(array($this, 'auto_validate_' . $fieldName), $value);
            if ($returnValue) {
                $returnValue = call_user_func_array(array($this, 'validate_' . $fieldName), $value);
            }
        }

        return $returnValue;
    }
}

This now affords me the luxury of being able to do the following:

// Does a value validate in static context?
$bar = $_REQUEST['bar'];
$valid = Foo::auto_validate_bar($bar);

// Does a value validate against the business logic?
$bar = $_REQUEST['bar'];
$valid = $foo->validate_bar($bar);

// Does the current instance value validate against the business logic?
$valid = $foo->validate_bar($foo->bar);

// Does the current instance value validate against both generic and business logic?
$valid = $foo->validate('bar', $foo->bar);

Now I can afford myself the luxury of autogenerating a generic class, in similar fashion to Symfony validators, to accomplish the validation for the Foo object.

What do you folks think?

Leave a Comment