We're randomly getting some very strange error logs. They don't happen on every page hit, even with the same parameters/actions/etc, and they don't seem repeatable, each one is different in its crash location, and context. But almost all have incorrect __PHP_Incomplete_Class_Name as the cause.
One such error is:
main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "LoginLogging" of the object you are trying to operate on was loaded before unserialize() gets called or provide a __autoload() function to load the class definition
The problem being, there is no "LoginLogging" class. The object it's referring to was of type ScormElement when it was saved into the session. Doing a dump of the variable gives:
__PHP_Incomplete_Class::__set_state(array(
'__PHP_Incomplete_Class_Name' =&g开发者_StackOverflowt; 'LoginLogging',
'intUserId' => '64576',
'__intUserId' => '64576',
'intScormId' => '665',
'__intScormId' => '665',
'intScoId' => '9255',
'__intScoId' => '9255',
'strElement' => 'cmi.core.lesson_location',
'__strElement' => 'cmi.core.lesson_location',
'strValue' => '1',
'dttTimeModified' => QDateTime::__set_state(array(
'blnDateNull' => false,
'blnTimeNull' => false,
'strSerializedData' => '2011-08-31T08:05:22-0600',
'date' => '2011-08-31 08:05:22',
'timezone_type' => 1,
'timezone' => '-06:00',
)),
'__strVirtualAttributeArray' => array (),
'__blnRestored' => true,
'objUser' => NULL,
'objScorm' => NULL,
)
All the properties are retained correctly, and match the class definition for ScormElement. But the class name is wrong. There is no class named LoginLogging.
What is causing this and how do we fix it???
Edit: This is just an example. Other errors are very similar in structure, but affect other class types, and have different incomplete names. However, ALL incomplete names have the same string length of the correct class name.
Edit 2011-10-27: I'm still seeing these error logs, and have had no success in finding a solution. Any help would be appreciated.
PHP 5.3.3, APC, default session handler.
As written in the quote in your question __PHP_Incomplete_Class_Name
is a special class name in PHP that is used whenever the class definition could not be found when unserializing (unserialize()
).
It's suggested to either ensure the class definition is available or to provide some autoloading for the missing class.
You commented that PHP is looking for the wrong classname here:
wrong: LoginLogging
right: ScormElement
It's hard to say with the information given why the classname is being changed on serialization/unserialization. The information you've given (especially the dump) in your question is incomplete.
So the options are limited to some general suggestions:
You could inspect the serialized string which classname is given in there so you could at least say if it happens with serialization or unserialization. You can easily inspect serialized data with the Serialized PHP Library which has a text-dumper for debug purposes.
Additionally there is the unserialize_callback_func
Ini-Directive you can use to further trace the problem.
<?php
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
// unserialize_callback_func directive available as of PHP 4.2.0
ini_set('unserialize_callback_func', 'mycallback'); // set your callback_function
function mycallback($classname)
{
// just include a file containing your classdefinition
// you get $classname to figure out which classdefinition is required
}
As you write the problem does not occur any longer, I suspect that at some point the serialization on your site was broken storing invalid data. Which framework/libraries/application are you using? Which component takes care about serialization?
If your trying to access a property method of an object or serialized value you've stored in a $_SESSION variable and you included the class after calling session_start() try including the class before calling session_start();
This happens when we try to initialize the session before loading the class definitions for the object we are trying to save into the session.
you can use simply json methods in PHP
json_encode that array and again json_decode that array and save it in a variable and than print that variable. you will get a simple array.
eg.
$array = array(); // this is your array variable to whom you are trying to save in a session
$encode = json_encode($array);
$decode = json_decode($encode);
echo '<pre>';
print_r($decode);
it will work surely.
Are you, by any chance, using some opcode cache (e.g. APC, XCache) or some debugger? They sometimes cause weird things to happen. If there isn't and never was a LoginLogging class in your project, but yours is not the only project on the server, I would bid on the cache.
To include the class before the session_start() works fine for me. =)
Hakre's suggestion to look at session_write_close led me to what appears to be a reliable fix:
register_shutdown_function('session_write_close');
This forces the session to be written out before any memory cleanup and class unloading occurs. This is important due to a change in PHP that can result in a race condition between APC removing class references and PHP writing out the session data: http://news.php.net/php.internals/46999
When you try to unserialize a variable, php must know the structure of the object. Try to include your class before unserialize. Which class? the one that holds those properties shown in your code. include('pathtoyourclass/classname.php') or include_once('pathtoyourclass/classname.php').
Good luck!
I use this function to solve this problem
$user = $_SESSION['login'];
$auth_user= fixObject($user);
function fixObject(&$object) {
if (!is_object($object) && gettype($object) == 'object')
return ($object = unserialize(serialize($object)));
return $object;
}
It is the serialization issue in your code.It may be your code for some reason could not initialize the object and in next part of your code tries to convert that object to string or some other data type.
Just inspect your code, properly initialize your objects.
Check if you are using serialize()/unserialize() method.
Are you receiving this serialized object from a service/stream or reading it from a file? I've seen it happen in a client-server setting the client side object and the server side objects differ very slightly... maybe have a property that the other doesn't have. This also happens when you serialize an object, save it to file, then refactor code that removes a class and then try's to deserialize the object.
Then when it gets deserialized and tries to instantiate the needed classes they don't exist.
The error is clear and straightforward, you're creating a object for which the class has not been loaded.
I'd do a string search on your code, find where the needed class is located, and make a simple autoloader (or just a raw include/require) of the file. Just get the class it needs loaded somehow.
If the class really doesn't exist anywhere, try checking earlier revisions (I'm assuming you have version control of some type) for existence of the class. If you're deserializing an object generated by another system check that system out as well.
精彩评论