|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-08-14 09:40 UTC] zerspam at mail dot ru
Description:
------------
Seems like __sleep() does not being invoked when fatal error was risen.
Test script:
---------------
set_error_handler('my_error_handler');
session_start();
$obj = new myclass();
$_SESSION['obj'] = $obj;
$a->b();
class myclass
{
private $a = 1;
private $b = 2;
public function __sleep()
{
return array('a');
}
}
function my_error_handler($code, $error, $file = NULL, $line = NULL)
{
throw new ErrorException($error, $code, 0, $file, $line);
}
Expected result:
----------------
Object with only 'a' property in session file
Actual result:
--------------
Object with 'a' and 'b' properties in session file
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 01:00:02 2025 UTC |
>However if your class implements Serializable everything works as >expected when there is a fatal error. Not true. See this example: --------- set_error_handler('my_error_handler'); session_start(); $a->b(); class myclass implements Serializable { private $a= 1; private $b = 2; public function serialize() { var_dump("serialize"); return serialize(array('a')); } public function unserialize($data) { var_dump("unserialize"); return unserialize($data); } } function my_error_handler($code, $error, $file = NULL, $line = NULL) { throw new ErrorException($error, $code, 0, $file, $line); } $obj = new myclass(); $_SESSION['obj'] = $obj; --------- Whether your class implements Serializable or not, serializers are called on _request shutdown_ which never happens in case of fatal error, because fatal error means BOOM!, exit. And to be honest, I don't see anything wrong here. Your script FAILED with a fatal error, did you expect PHP to ignore it an go on running?Tony, I guess I didn't explain myself very well. Serializable isn't the problem. The issue is with the __wakeup/__sleep() methods. Let's take these two example classes: --------------- class myclass implements Serializable { private $a = 1; private $b = 2; public function serialize() { return serialize(array('a' => $this->a)); } public function unserialize($data) { foreach(unserialize($data) as $name => $var) { $this->{$name} = $var; } } } class myclass2 { private $a = 1; private $b = 2; public function __sleep() { return array('a'); } public function __wakeup() { } } I would expect both classes to serialize the 'a' property and they both do. However when there is a fatal error in your code (like your example code), both the a and b properties from the myclass2 class are serialized. Here is an example of my session data using your example code and the two classes above. Using Serializable: obj|C:7:"myclass":18:{a:1:{s:1:"a";i:1;}} (without exception) obj|N; (with exception) Using sleep/wakeup: obj|O:8:"myclass2":1:{s:11:"myclass2a";i:1;} (without exception) obj|O:8:"myclass2":2:{s:11:"myclass2a";i:1;s:11:"myclass2b";i:2;} (with exception) Notice how when using the __sleep/__wakeup methods the whole object is stored instead of nothing (or just the data in the __sleep method). Hopefully that explains the issue a little better.