我想验证对象属性。因为我们不太了解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);
如果有人知道如何做得更好,请发送小费!
谢谢大家