Why UnexpectedValueException
is thrown in session_start()
?
I have object which has property of SPLObjectstorage
. That object is assigned to session like
$_SESSION['foo'] = $barObject;
I suspect that internal session serializing facing problem to decode it. I store the session in database and it looks like it is serializing the objectStorage
but can not decode it.
Sample session data
self|O:4:"User":8:{s:5:"�*�id";N;s:7:"�*�nick";N;s:13:"�*�reputation";i:1;s:11:"�*�password";N;s:8:"�*�email";N;s:7:"�*�crud";O:10:"CRUDobject":2:{s:13:"�*�fieldCache";a:0:{}s:13:"�*�dependency";r:1;}s:7:"�*�auth";N;s:11:"�*�roleList";C:11:"RoleStorage":23:{x:i:1;N;,r:13;;m:a:0:{}}}
Rolestorage
is extends of SPLObjectstorage
session_decode()
on above string also returns false
any ideas?
removing the roleList
attribute makes it serialize properly.
If I separately do
$sr = serialize($roles); // $roles is RoleStorage object
var_dump($sr);
var_dump(unserialize($sr));
It prints string 'C:11:"RoleStorage":22:{x:i:1;N;,r:3;;m:a:0:{}}' (length=46)
and then fails with same message while unserializing. I have no clue why this is happening.
Note: while attaching object to RoleStorage
I used the object itself as data. Means it is stored as reference. I don't know how (if) does serialize()
handles internally this.
Objects with the name RoleStorage
raises a couple of flags for me. Often, this object does contain a resource of sorts, or a reference to a built-in PHP object. Resources can't be serialized, nor can some PHP built-in types be serialized. Consider implementing the magic __sleep
and __wakeup
methods in those cases.
Say you have a PDO
reference somewhere in the RoleStorage
object, then these magic properties might look something like this:
public function __sleep()
{
$this->pdo->commit();//commit && close
$this->pdo = array($dsn, $user, $pwd, array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
return serialize($this);
}
public function __wakeup()
{
$this->pdo = new PDO($this->pdo[0], $this->pdo[1], $this->pdo[2], $this->pdo[3]);
}
But since you say the RoleStorage
objects is a child of SPLObjectStorage
, you'd be better off overriding the SPLObjectStorage
's implementation of the Serializable
interface:
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.
I'd suggest declaring iterating over all properties in the child class's serialize
method, and store that data into an array. Return that array serialized, and unserialize that string back in the unserialize
method, reassigning every property in a loop.
If SPLObjectStorage
has private properties, you can get to them like so:
class RoleStorage extends SPLObjectStorage
implements Serializable
{
public function serialize()
{
return serialize((array) $this);
}
public function unserialize($string)
{
$array = unserialize($string);
foreach($array as $property => $value)
{
$property = explode("\0", $property);//private & protected properties
$this->{end($property)} = $value;
}
}
}
For details on the explode("\0",$property);
, refer to the manual, or check this question
I have no clue why this is happening
In your PHP version and with your concrete script it is not possible to serialize an object based on SPLObjectStorage
unless you take care of the serialization your own.
If you see this part of your serialized string:
C:11:"RoleStorage":23:{x:i:1;N;,r:13;;m:a:0:{}}
This represents the RoleStorage
object. The big C at the beginning stands for:
C - Object implementing serializeable Interface
So the object itself is responsible here about the serialization and unserialization. You can normally expect this works, however not all software is without bugs.
In your case it looks like PHP made a mistake. The internal format here is:
x:i:1;N;,r:13;;m:a:0:{}
^^^^^^^
And the problem is at the highlighted position, this requires a serialized object, not NULL. And it's not comma-terminated with a reference (r:13
here), but with null (N
) to be working.
So looks like a hick-up triggered by referencing some earlier object (take care that this referencing is not the same as references / variable aliases in userland PHP).
So how to go on?
It's time you start to isolate your problem and create a self-contained, reproduceable example out of it. This is necessary to further look into the issue as you see it. This is important for two reasons:
I did run some tests for a work-around, however so far I'm not able to reproduce your issue so I can not really suggest how to work around the issue as I don't have it here.
There has been a bug closed recently regarding an issue similar to this. Depending on the php version you are running, you may still be affected. The affected version is 5.3.15.
Excerpt:
[2012-07-27 16:08 UTC] j dot henge-ernst at interexa dot de
The problem is that the unserialize of ArrayIterator (and also maybe ArrayObject or other SPL classes) can not dereference object references.
If you are affected by this bug, then you may be right that it is related to dereferencing. Perhaps try a newer version of PHP to see if it still happens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With