我知道有一个类似的主题,但我已经尝试了他们的建议并且它没有用。
在php中,当一个对象被序列化时,有一个选项在该类中定义一个魔术函数__sleep
,它应该返回一个数组,其中包含将被序列化的所有对象属性的值。但是在php.net中写道,如果我们为从另一个类扩展的类的对象定义__sleep
方法,那么我们就无法写入表示父类的私有属性的数组值。问题是他们为这种情况提出了一个解决方案,我并没有真正理解他们试图暗示的内容。
以下是撰写内容:
注意:
__sleep()无法返回父类中私有属性的名称。执行此操作将导致E_NOTICE级别错误。相反,您可以使用Serializable接口。
以下是链接:http://www.php.net/manual/en/language.oop5.magic.php
另外,在this thread中,他们提出了我尝试过的内容并且无法正常工作并发送给我:
注意:serialize():“name”作为成员变量从__sleep()返回,但在第43行的C:\ xampp \ htdocs \ questions \ sleep_private_father.php中不存在
这是脚本:
<?php
class a
{
private $name ;
private $age ;
function __construct($name, $age)
{
$this->name = $name ;
$this->age = $age ;
}
function __sleep()
{
$vec = array("name") ;
return $vec ;
}
}
class b extends a
{
private $last_name ;
function __construct($name, $age ,$last_name)
{
parent::__construct($name, $age) ;
$this->last_name = $last_name ;
}
function __sleep()
{
$array = parent::__sleep() ;
array_push( $array, 'last_name' );
return $array ;
}
}
$ob = new b("michal" , 26 , "smith") ;
var_dump($ob) ;
$ob_ser = serialize($ob) ;
var_dump(unserialize($ob_ser)) ;
?>
我也很好奇php.net建议使用serializble接口的方式。
答案 0 :(得分:1)
私有运算符意味着属性或函数只能在类中使用,并且不能扩展。如果您希望实现机制在子类中存储属性,您应该尝试类似:
class foo{
protected $test = 'a';
public function __sleep() {
return array('test');
}
}
class bar extends foo{
public function getTest(){
return $this->test;
}
}
$bar = new bar();
$serialized = serialize($bar);
$object = unserialize($serialized);
echo $object->getTest();
OR
class foo{
protected $test = 'a';
}
class bar extends foo{
public function __sleep() {
return array('test');
}
public function getTest(){
return $this->test;
}
}
$bar = new bar();
$serialized = serialize($bar);
$object = unserialize($serialized);
echo $object->getTest();
最后一种方式我使用运营商保护而非私人
答案 1 :(得分:0)
请注意您的链接(php.net)意味着:
Note:
It is not possible for __sleep() to return names of private properties
in parent classes. Doing this will result in an E_NOTICE level error.
Instead you may use the Serializable interface.
如果您尝试使用私有属性在__sleep方法数组中重新生成(如果它是父类或子类,则无关紧要),您总会收到通知错误。可以避免此通知并使用可序列化接口获取私有属性的名称。
如果您的类实现了可序列化接口,则不应使用__sleep方法beacuse实现此接口的类不再支持__sleep()和__wakeup()方法。 :
Serializable {
/* Methods */
abstract public string serialize ( void )
abstract public void unserialize ( string $serialized )
}
序列化将在您的对象将序列化状态(对象 - &gt;字符串)时调用,并在您的对象将进行反序列化(字符串 - &gt;对象)时反序列化。您无法读取子类中的私有属性父类(当您尝试从子类中的方法获取此属性时)。例如:
class foo implements Serializable{
private $id;
public function serialize() {
return serialize('hello world');
}
public function unserialize($serialized) {
$this->id = unserialize($serialized);
}
public function get_id_from_foo(){
return $this->id;
}
}
class bar extends foo{
public function get_id_from_bar(){
return $this->id;
}
}
$bar = new bar();
$serializedBar = serialize($bar);
$unserializedBar = unserialize($serializedBar);
echo $unserializedBar->get_id_from_bar();
//RESULT : Undefined property: bar::$id
但是如果你将foo class private $ id更改为protected $ id,你就会得到'hello world'。
在其他情况下,当您尝试从父级方法extendend获取私有属性时,例如:
class foo implements Serializable{
private $id;
public function serialize() {
return serialize('hello world');
}
public function unserialize($serialized) {
$this->id = unserialize($serialized);
}
public function get_foo_id_from_parent(){
return $this->id;
}
}
class bar extends foo{
public function set_id(){
$this->id = 'something else';
}
public function get_foo_id_from_bar(){
return $this->id;
}
}
$bar = new bar();
$bar->set_id();
$serializedBar = serialize($bar);
$unserializedBar = unserialize($serializedBar);
echo $unserializedBar->get_foo_id_from_parent();
//RESULT 'hello world'; But this property is from parent!!
答案 2 :(得分:0)
好的,你们都给了我解决我确切问题的想法,这就是得到一个结果,好像我可以在扩展类的对象的sleep方法中定义一个来自父类的私有属性。这是我的解决方案:
<?php
class foo implements Serializable
{
private $id;
private $name ;
public function serialize()
{
$array_properties_to_serialize = array('id' => $this->id) ;
// this if will indicate if an object from the foo class invoked the method
//or an object from the extend class (bar)
if (get_class($this) == "foo")
{
// foo object invoked the method , so we will want to serialize only the $id property
return serialize($array_properties_to_serialize);
}
elseif (get_class($this) == "bar")
{
// bar object invoked the method so we will want to add to the array of properties
//the $last_name property from the bar class, and then serialize it
return $array_properties_to_serialize ;
}
}
public function unserialize($serialized)
{
$array_properties_unserialized = unserialize($serialized);
$this->id = $array_properties_unserialized['id'] ;
if (get_class($this) == "bar")
{
// bar object invoked the method so we will send to the overriding method the $array_properties_unserialized
// so it could set the properties of the extended object accordingly.
return $array_properties_unserialized ;
}
}
public function __construct($id,$name)
{
$this->name = $name ;
$this->id = $id ;
}
}
class bar extends foo
{
private $last_name ;
public function serialize()
{
$array_properties_to_serialize = parent::serialize() ;
$array_properties_to_serialize["last_name"] = $this->last_name ;
return serialize($array_properties_to_serialize);
}
public function unserialize($serialized)
{
$array_properties_unserialized = parent::unserialize($serialized) ;
$this->last_name = $array_properties_unserialized['last_name']; ;
}
public function __construct($id, $name , $last_name)
{
parent::__construct($id, $name) ;
$this->last_name = $last_name ;
}
}
echo "bar object: <br>" ;
$bar = new bar(12 , "tom" , "smith");
var_dump($bar) ;
$ob_ser = serialize($bar) ;
$ob_unser = unserialize($ob_ser) ;
echo "unserialized bar object (didnt include the \$name property): <br>" ;
var_dump($ob_unser) ;
$foo = new foo(11 , "frank") ;
echo "foo object: <br>" ;
var_dump($foo) ;
$ob_ser = serialize($foo) ;
$ob_unser = unserialize($ob_ser) ;
echo "unserialized foo object (didnt include the \$name property): <br>" ;
var_dump($ob_unser) ;
?>
答案 3 :(得分:0)
另一种解决方案:
<?php
class foo
{
private $id;
private $name ;
public function serialize()
{
$array_properties_to_serialize = array('id' => $this->id) ;
return serialize($array_properties_to_serialize);
}
// will be called only on a foo object because it doesnt implements serializable
// when serialize a bar object it will only invoke the serialize method in the bar class
public function __sleep()
{
return array('id') ;
}
public function getID()
{
return $this->id ;
}
public function setId($id)
{
$this->id = $id ;
}
public function unserialize($serialized)
{
$array_properties_unserialized = unserialize($serialized);
$this->id = $array_properties_unserialized['id'] ;
}
public function __construct($id,$name)
{
$this->name = $name ;
$this->id = $id ;
}
}
class bar extends foo implements Serializable
{
private $last_name ;
public function serialize()
{
$array_properties_to_serialize['id'] = $this->getID() ;
$array_properties_to_serialize["last_name"] = $this->last_name ;
return serialize($array_properties_to_serialize);
}
public function unserialize($serialized)
{
$array_properties_unserialized = unserialize($serialized) ;
$this->last_name = $array_properties_unserialized['last_name'];
$this->setId($array_properties_unserialized['id']) ;
}
public function __construct($id, $name , $last_name)
{
parent::__construct($id, $name) ;
$this->last_name = $last_name ;
}
}
echo "bar object: <br>" ;
$bar = new bar(12 , "tom" , "smith");
var_dump($bar) ;
$ob_ser = serialize($bar) ;
$ob_unser = unserialize($ob_ser) ;
echo "unserialized bar object (didnt include the \$name property): <br>" ;
var_dump($ob_unser) ;
$foo = new foo(11 , "john") ;
echo "foo object: <br>" ;
var_dump($foo) ;
$ob_ser = serialize($foo) ;
$ob_unser = unserialize($ob_ser) ;
echo "unserialized foo object (didnt include the \$name property): <br>" ;
var_dump($ob_unser) ;
?>
答案 4 :(得分:0)
如果您这样命名父属性"\0". parent::class. "\0parentProperty"
<?php
namespace bed {
class A {
private $id=5;
protected $b;
public $c;
public function __sleep()
{
return ['id'];
}
}
class B extends A{
public function __sleep(){
return parent::__sleep();
}
}
class D extends A{
public function __sleep(){
return ["\0bed\A\0id"];
}
}
class CoolD extends A {
private $d;
protected $e;
public $f;
public function __sleep(){
$allProperties = [];
$reflection = new \ReflectionClass($this);
do{
foreach ($reflection->getProperties() as $prop) {
$allProperties[($prop->isPrivate()
? "\0" . $prop->getDeclaringClass()->getName() . "\0" . $prop->getName()
: $prop->getName())] = true;
}
}while($reflection = $reflection->getParentClass());
return array_keys($allProperties);
}
}
class C extends A{
}
// var_dump(serialize(new C)); - not working
// var_dump(serialize(new B)); - not working
var_dump(serialize(new D));
var_dump(serialize(new CoolD));
}