PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!
<?php
class A
{
private $_q = 10;
}
class B extends A
{
private $_qq = 20;
public function __sleep()
{
return array('_qq', "\0A\0_q");
}
}
$q = new B;
$e = unserialize(serialize($q));
var_dump($q, $e);
I wouldn't use this approach though as it's, frankly, a hack relying on knowledge of the internal representation of objects, but nevertheless it's possible.
I knew there was a way to get access to private variables of an object by casting the object to array and using this null notation. I figured it was worth a try to use this in __sleep() - turned out it works there as well.
I thought this casting hack would no longer work, but now that I tested it it still works in PHP 5.3.7 (debian flavor).
This is a side effect as far as I know. I didn't dig the php source, but I think I read Sebastian considered using it in PHPUnit before ReflectionProperty::setAccessible() was introduced.
class PHPObject implements Serializable {
private $transientVar = 40;
/**
* The inner property map that contains the serializable data.
* Un serializable objects cannot be stored in here.
*
* @var array
*/
private $data = array();
/**
* Constructor
*
* @param mixed $data
* @return unknown_type
*/
public function __construct($data = array())
{
if (empty($data)) {
$this->data = array();
} else if (is_array($data)) {
$this->data = $data;
} else if (is_object($data) && $data instanceof stdClass) {
$this->data = (array) $data;
}
//lost when unserialized
$this->transientVar = 100;
}
/**
* Magic method facilitating access to private properties
* to set value to the property identified by its name
*
* @param string $name the property name
* @param mixed $value the value to be set
*/
public function __set($name, $value)
{
$this->data[$name] = $value;
}
/**
* Magic method facilitating access to private properties
* returning the property value associated with a property name
*
* @param string $name the property name
* @return mixed the value held by this property
*/
public function __get($name)
{
if ($this->__isset($name)) {
return $this->data[$name];
}
return null;
}
/**
* Magic method that unsets a property; Property will still
* exist but will be undeclared
*
* @param string $name the property name
*/
public function __unset($name)
{
if ($this->__isset($name)) {
unset($this->data[$name]);
}
}
/**
* Magic method that checks if the property is declared for
* this bean instance
*
* @param string $name the property name
* @return boolean true if property exists and declared
* else false
*/
public function __isset($name)
{
return array_key_exists($name, $this->data);
}
/**
* String representation of an object
*
* @return string the object respresented as a string
*/
public function __toString()
{
return get_class($this) . hashcode();
}
/**
* This function is called prior to serialization of an object
* @deprecated
*/
public function __sleep()
{}
/**
* This function is called after unserialization of an object
* @deprecated
*/
public function __wakeup()
{}
/**
* Equality test.
* Default implementatio is object identity test.
*
* @param object $obj other object
* @return bool true if this object and the other object are the same instance.
*/
public function equals($obj)
{
return $this === $obj;
}
/**
* Returns object ID hash code.
* This return value is available on PHP 5.2.0 or later.
*
* @return string object hash code
*/
public function hashCode()
{
return System::identityHashCode($this);
}
/**
* (non-PHPdoc)
* @see Serializable::serialize()
*/
public function serialize()
{
return serialize($this->data);
}
/**
* (non-PHPdoc)
* @see Serializable::unserialize()
*/
public function unserialize($str)
{
$this->data = unserialize($str);
}
}
Treat this as java.lang.Object and extend it everywhere in your hirearchy, and bingo. Magic methods to your rescue.
If you want the object as a whole to be not serializable, override serialize() and unserialize() [no recommended], or use a marker interface like java.io.Serializable.