php __PHP_Incomplete_Class_Name 错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7272813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:22:27  来源:igfitidea点击:

__PHP_Incomplete_Class_Name wrong

phpsessionserializationapc

提问by VexedPanda

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.

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

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 beforeunserialize() gets called or provide a __autoload() function to load the class definition

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

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:

问题是,没有“LoginLogging”类。它所指的对象在保存到会话中时属于 ScorpElement 类型。做一个变量的转储给出:

__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,
)

All the properties are retained correctly, and match the class definition for ScormElement. But the class name is wrong. There isno class named LoginLogging.

所有属性都被正确保留,并与 ScormElement 的类定义相匹配。但是类名是错误的。这里没有名为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 lengthof 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.

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

PHP 5.3.3, APC, default session handler.

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

采纳答案by VexedPanda

Hakre's suggestion to look at session_write_close led me to what appears to be a reliable fix:

Hakre 建议查看 session_write_close 使我找到了一个可靠的修复方法:

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

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

回答by hakre

As written in the quote in your question __PHP_Incomplete_Class_Nameis a specialclass name in PHP that is used whenever the class definition could not be found when unserializing (unserialize()).

正如您问题中的引用所写的那样,PHP 中__PHP_Incomplete_Class_Name有一个特殊的类名,只要在反序列化 ( 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:

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

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 Librarywhich has a text-dumper for debug purposes.

您可以检查其中给出的类名的序列化字符串,因此您至少可以说明它是在序列化还是反序列化时发生的。您可以使用序列化 PHP 库轻松检查序列化数据,该具有用于调试目的的文本转储程序。

Additionally there is the unserialize_callback_funcIni-Directiveyou can use to further trace the problem.

此外,您还可以使用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
}

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?

当您编写时,问题不再发生,我怀疑在某些时候您站点上的序列化被破坏,存储无效数据。您使用的是哪个框架/库/应用程序?哪个组件负责序列化?

回答by gus

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 aftercalling session_start() try including the class beforecalling session_start();

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

回答by Shiv Aggarwal

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

你可以在 PHP 中简单地使用 json 方法

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.

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

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.

它肯定会起作用。

回答by Wellington Lorindo

To include the class before the session_start() works fine for me. =)

在 session_start() 之前包含该类对我来说很好。=)

回答by a sad dude

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.

您是否正在使用某种操作码缓存(例如 APC、XCache)或某种调试器?他们有时会导致奇怪的事情发生。如果您的项目中没有并且从来没有 LoginLogging 类,但您的项目不是服务器上唯一的项目,我会竞标缓存。

回答by FerYepes

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').

当您尝试反序列化一个变量时,php 必须知道该对象的结构。在反序列化之前尝试包含您的类。哪一堂课?保存代码中显示的那些属性的那个。include('pathtoyourclass/classname.php') 或 include_once('pathtoyourclass/classname.php')。

Good luck!

祝你好运!

回答by IT Sekuro

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;
}

回答by Dev

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.

检查您是否正在使用 serialize()/unserialize() 方法。

回答by Ray

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.

如果该类在任何地方都不存在,请尝试检查早期版本(我假设您具有某种类型的版本控制)是否存在该类。如果您正在反序列化由另一个系统生成的对象,请检查该系统。