Php 创建我自己的(非数据库)fetch_对象函数
在php mysql/mysqli/postgre/etc中。。。有fetch_object函数,您可以在其中为数据行获取对象。默认情况下,它将返回一个对象Php 创建我自己的(非数据库)fetch_对象函数,php,oop,Php,Oop,在php mysql/mysqli/postgre/etc中。。。有fetch_object函数,您可以在其中为数据行获取对象。默认情况下,它将返回一个对象stdClass,但您也可以为构造函数定义一个类名和一个参数数组 我想用一组简单的值做同样的事情。最好在调用构造函数之前设置对象的属性,这与数据库函数显示的行为相同。然而,这似乎是不可能的 创建属性设置为的对象的唯一方法似乎是。但该示例仍然会创建一个新对象,然后从未序列化的对象设置该对象的属性,以确保调用构造函数。但这意味着在设置属性之前调用
stdClass
,但您也可以为构造函数定义一个类名和一个参数数组
我想用一组简单的值做同样的事情。最好在调用构造函数之前设置对象的属性,这与数据库函数显示的行为相同。然而,这似乎是不可能的
创建属性设置为的对象的唯一方法似乎是。但该示例仍然会创建一个新对象,然后从未序列化的对象设置该对象的属性,以确保调用构造函数。但这意味着在设置属性之前调用构造函数
简言之,我希望:
array\u fetch\u对象(array$properties,string$class\u name[,array$params])
设置属性后调用构造函数。您可以将数组强制转换为对象,如下所示:
$array = array('a' => 'a', 'b' => 'c');
$object = (object) $array;
或者只是:
$object = (object) array('a' => 'a', 'b' => 'c');
这将为您提供一个具有数组属性的stdClass对象。好的,我没想到这会起作用,但它确实:
class TestObject {
public $property;
public $preset;
public function __construct($param) {
$this->property = $param;
}
}
$object = unserialize('O:10:"TestObject":1:{s:6:"preset";i:1;}');
$object->__construct(1);
print_r($object);
结果:
TestObject Object
(
[property] => 1
[preset] => 1
)
我只需要在创建序列化字符串之前检查属性的访问类型,因为私有属性的类名是在前面加上的。然而,调用一个已经构造的对象的构造函数会继续工作吗?最后,我编写了下面的类,它使用一个伪造的字符串来执行任务。它使用反射来确定属性的访问类型以及构造函数的名称(如果有) 课程的核心是以下几行:
$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;
}
}
有什么理由不能直接使用
new
$x=new$class($argument)
在调用构造函数之前不会设置属性,并且无法设置私有属性。这将导致stdClass的对象,该对象没有任何类似于通过传递$class\u名称获取的对象的方法。我想要一个特定类的对象。好的,我的另一个答案是使用各种各样的东西,你甚至不能在PHP中做。很抱歉。我很想看看你有什么想法。你能加入一个自定义类吗?我没有安装PHP,所以我不能尝试。不,你不能。另请参见此处:、此处:和此讨论:。