PHP验证对象的属性

时间:2018-02-10 14:45:27

标签: php validation object properties

我想验证对象属性。因为我们不太了解PHP OOP,所以我们选择了这种方式:

首先创建验证程序

namespace Validator;

/**
 * Class ObjectPropertyValidator - Validate object, test if have all property
 * @package Validator
 */
class ObjectPropertyValidator {

    /**
     * @param object $object
     *
     * @throws ValidatorException
     */
    public static function validate($object) {
        $reflectionClass = new \ReflectionClass(get_called_class());
        foreach ($reflectionClass->getProperties() as $property) {
            $name = $property->name;
            if (!property_exists($object, $name)) {
                throw new ValidatorException('Object not have property ' . $name, 0);
            }
            new PropertyValidator($property->getDocComment(), $object->$name, $name);
        }
    }
}

接下来我创建属性验证器(我没有验证所有类型):

namespace Validator;

/**
 * Class PropertyValidator - Parse PHPDOC to pieces and validate input property
 * @package Validator
 */
class PropertyValidator {

    const DOC_PATTERN = '/@var\s+(?<object>\\\?)(?<type>[0-9A-Za-z\\\]+)(?<array>\[?\]?)/';
    const DOC_IS_ARRAY = '[]';
    const DOC_IS_OBJECT = '\\';

    /** @var bool */
    public $is_Array = false;
    /** @var bool */
    public $is_Object = false;
    /** @var string */
    public $type = '';

    /**
     * PropertyValidator constructor.
     *
     * Where make validating over PHPDOC over $property
     *
     * @param string $doc PHPDOC
     * @param mixed $property Validating Property
     * @param string $name Name of property
     */
    public function __construct($doc, $property, $name) {
        $this->analyzePHPDOC($doc);
        $this->validate($property, $name);
    }

    /**
     * @param string $doc
     */
    private function analyzePHPDOC($doc) {
        if (preg_match(self::DOC_PATTERN, $doc, $matches)) {
            $this->is_Array = $matches['array'] === self::DOC_IS_ARRAY;
            $this->type = $matches['object'] . $matches['type'];
            $this->is_Object = $matches['object'] === self::DOC_IS_OBJECT;
        }
    }

    /**
     * @param object $property
     * @param string $name
     *
     * @throws ValidatorException
     */
    private function validate($property, $name) {
        if ($this->is_Array) {
            if (!is_array($property)) {
                throw new ValidatorException('Object not have property ' . $name . ' type array', 0);
            }
            if ($this->is_Object) {
                $validator = new $this->type();
                foreach ($property as $subobject) {
                    /** @var ObjectPropertyValidator $validator */
                    $validator::validate($subobject);
                }
            }
        } else {
            if ($this->is_Object) {
                $validator = new $this->type();
                /** @var ObjectPropertyValidator $validator */
                $validator::validate($property);
            } else {
                switch ($this->type) {
                    case 'string':
                        if (!is_string($property)) {
                            throw new ValidatorException('Property ' . $name . ' is not string', 0);
                        }
                        break;
                    case 'int':
                    case 'integer':
                        if (!is_numeric($property)) {
                            throw new ValidatorException('Property ' . $name . ' is not numeric', 0);
                        }
                        break;
                }
            }
        }
    }
}

这里我有一个用于验证的骨架类(在单独的文件中):

namespace Object;

use Validator\ObjectPropertyValidator;

class SkeletonForValidatingA extends ObjectPropertyValidator {
    /** @var  string */
    public  $someProperty;
    /** @var \Object\SkeletonForValidatingB[] */
    public  $somePropertyArray;
}

namespace Object;

use Validator\ObjectPropertyValidator;

class SkeletonForValidatingB extends ObjectPropertyValidator {
    /** @var  int*/
    public $someProperty;
}

最后如何使用all:

$parameters = '{"someProperty":"some text", "somePropertyArray":[{"someProperty":1}]}';
$parameters = Zend_Json::decode($parameters, false);

SkeletonForValidatingA::validate($parameters);

如果有人知道如何做得更好,请发送小费!

谢谢大家

0 个答案:

没有答案