__PHP_Incomplete_Class_Name错误

Vex*_*nda 12 php session serialization apc

我们随机得到一些非常奇怪的错误日志.即使使用相同的参数/动作/等,它们也不会发生在每个页面上,并且它们似乎不可重复,每个页面的崩溃位置和上下文都不同.但几乎所有都有错误的__PHP_Incomplete_Class_Name作为原因.

一个这样的错误是:

main():脚本尝试执行方法或访问不完整对象的属性.请确保在调用unserialize()之前加载了您正在尝试操作的对象的类定义"LoginLogging",或者提供__autoload()函数来加载类定义

问题是,没有"LoginLogging"类.当它被保存到会话中时,它所引用的对象是ScormElement类型.转储变量给出:

__PHP_Incomplete_Class::__set_state(array(
 '__PHP_Incomplete_Class_Name' => '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,
)
Run Code Online (Sandbox Code Playgroud)

正确保留所有属性,并匹配ScormElement的类定义.但是班级名称是错误的.这里没有名为LoginLogging类.

造成这种情况的原因是什么?我们如何修复它?

编辑:这只是一个例子.其他错误在结构上非常相似,但会影响其他类类型,并且具有不同的不完整名称.但是,所有不完整的名称都具有正确类名的相同字符串长度.

编辑2011-10-27:我仍然看到这些错误日志,并且没有找到解决方案的成功.任何帮助,将不胜感激.

PHP 5.3.3,APC,默认会话处理程序.

hak*_*kre 24

正如您在问题中引用的那样,在PHP中__PHP_Incomplete_Class_Name是一个特殊的类名,只要在反序列化(unserialize())时找不到类定义就会使用它.

建议确保类定义可用或为缺少的类提供一些自动加载.

你评论说PHP在这里寻找错误的类名:

wrong: LoginLogging
right: ScormElement
Run Code Online (Sandbox Code Playgroud)

很难说给出为什么在序列化/反序列化时更改类名的信息.您在问题中提供的信息(特别是转储)不完整.

所以选项仅限于一些一般性建议:

您可以检查序列化字符串,在那里给出了哪个类名,这样您至少可以说是序列化还是反序列化.您可以使用Serialized PHP Library轻松检查序列化数据,该具有用于调试目的的文本转储程序.

此外,您还可以使用unserialize_callback_funcIni-Directive来进一步追踪问题.

<?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
}
Run Code Online (Sandbox Code Playgroud)

当你写的问题不再发生时,我怀疑在某些时候你的网站上的序列化被打破存储无效数据.您使用的是哪个框架/库/应用程序?哪个组件关注序列化?


gus*_*gus 9

如果您尝试访问对象或序列化值的属性方法,则存储在$ _SESSION变量中,并且调用session_start()之后包含该类,请调用session_start()之前尝试包含该类;


Shi*_*wal 5

当我们尝试在加载要保存到会话中的对象的类定义之前初始化会话时,就会发生这种情况。

您可以在 PHP 中使用简单的 json 方法

json_encode 该数组,再次 json_decode 该数组并将其保存在变量中,然后打印该变量。你会得到一个简单的数组。

例如。

$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);
Run Code Online (Sandbox Code Playgroud)

它肯定会起作用。


Vex*_*nda 2

Hakre 建议查看 session_write_close ,这让我找到了一个似乎可靠的修复方法:

register_shutdown_function('session_write_close');
Run Code Online (Sandbox Code Playgroud)

这会强制在进行任何内存清理和类卸载之前写出会话。这很重要,因为 PHP 中的更改可能导致 APC 删除类引用和 PHP 写出会话数据之间出现竞争条件:http://news.php.net/php.internals/46999