在 php mysql / mysqli / postgre / 等中...有 fetch_object 函数,您可以在其中获取数据行的对象。默认情况下它将返回一个对象stdClass
,但您也可以为构造函数定义一个 class_name 和一个参数数组。
我想用一组简单的值做同样的事情。优选地,设置对象的属性before调用构造函数,这与数据库函数显示的行为相同。然而,这似乎不可能。
创建具有属性集的对象的唯一方法似乎是反序列化预先构造的字符串 http://www.php.net/manual/en/language.types.type-juggling.php#100460。但该示例仍然创建一个新对象,然后从未序列化的对象中设置该对象的属性以确保调用构造函数。但这意味着在设置属性之前调用构造函数。
简而言之:我想要以下内容:
array_fetch_object(array $properties, string $class_name [, array $params ])
设置属性后调用构造函数。
最后,我编写了以下类,它使用反序列化伪造的字符串来执行任务。它使用反射来确定属性的访问类型是什么以及构造函数的名称是什么(如果有)。
该类的核心是下面一行:
$object = unserialize('O:'.strlen($class_name).':"'.$class_name.'"'.substr(serialize($properties), 1));
它序列化属性数组并将序列化的重命名为所需的类名。
class ObjectFactory {
private $properties;
private $constructors;
public function __construct() {
$this->properties = array();
$this->constructors = array();
}
private function setClass($class_name) {
$class = new ReflectionClass($class_name);
$this->properties[$class_name] = array();
foreach($class->getProperties() as $property) {
$name = $property->getName();
$modifier = $property->getModifiers();
if($modifier & ReflectionProperty::IS_STATIC) {
continue;
} else if($modifier & ReflectionProperty::IS_PUBLIC) {
$this->properties[$class_name][$name] = $name;
} else if($modifier & ReflectionProperty::IS_PROTECTED) {
$this->properties[$class_name][$name] = "\0*\0".$name; // prefix * with \0's unserializes to protected property
} else if($modifier & ReflectionProperty::IS_PRIVATE) {
$this->properties[$class_name][$name] = "\0".$class_name."\0".$name; // prefix class_name with \0's unserializes to private property
}
}
if($constructor = $class->getConstructor()) {
$this->constructors[$class_name] = $constructor->getName();
}
}
private function hasClassSet($class_name) {
return array_key_exists($class_name, $this->properties);
}
private function hasClassProperty($class_name, $property_name) {
if(!$this->hasClassSet($class_name))
$this->setClass($class_name);
return array_key_exists($property_name, $this->properties[$class_name]);
}
private function getClassProperty($class_name, $property_name) {
if(!$this->hasClassProperty($class_name, $property_name))
return false;
return $this->properties[$class_name][$property_name];
}
private function hasClassConstructor($class_name) {
if(!$this->hasClassSet($class_name))
$this->setClass($class_name);
return $this->constructors[$class_name] !== false;
}
private function getClassConstructor($class_name) {
if(!$this->hasClassConstructor($class_name))
return false;
return $this->constructors[$class_name];
}
public function fetch_object(array $assoc, $class_name = 'stdClass', array $params = array()) {
$properties = array();
foreach($assoc as $key => $value) {
if($property = $this->getClassProperty($class_name, $key)) {
$properties[$property] = $value;
}
}
$object = unserialize('O:'.strlen($class_name).':"'.$class_name.'"'.substr(serialize($properties), 1));
if($constructor = $this->getClassConstructor($class_name)) {
call_user_func_array(array($object, $constructor), $params);
}
return $object;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)