Ошибка __PHP_Incomplete_Class_Name

Мы произвольно получаем очень странные журналы ошибок. Они не происходят при каждом ударе по страницам, даже с теми же параметрами/действиями/и т.д., И они не кажутся повторяемыми, каждый из них отличается от местоположения сбоя и контекста. Но почти все имеют неправильную __PHP_Incomplete_Class_Name в качестве причины.

Одна из таких ошибок:

main(): script попытался выполнить метод или получить доступ к свойству неполного объекта. Убедитесь, что определение класса "LoginLogging" объекта, с которым вы пытаетесь работать, было загружено до вызова unserialize() или предоставления функции __autoload() для загрузки определения класса

Проблема заключается в том, что нет класса входа в систему. Объект, на который он ссылался, был типа 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,
)

Все свойства сохранены правильно и соответствуют определению класса для ScormElement. Но имя класса неверно. Нет класса с именем LoginLogging.

Что вызывает это и как мы его исправляем???

Изменить. Это пример. Другие ошибки очень похожи по структуре, но влияют на другие типы классов и имеют разные неполные имена. Однако ВСЕ неполные имена имеют одинаковую длину строки правильного имени класса.

Изменить 2011-10-27. Я все еще вижу эти журналы ошибок и не добился успеха в поиске решения. Любая помощь будет оценена.

PHP 5.3.3, APC, обработчик сеанса по умолчанию.

Ответ 1

Предложение Хакре посмотреть на session_write_close привело меня к тому, что кажется надежным решением:

register_shutdown_function('session_write_close');

Это заставляет сеанс записываться до того, как произойдет очистка памяти и разгрузка класса. Это важно из-за изменения PHP, которое может привести к условию гонки между APC, удаляющим ссылки на классы, и PHP, записывающим данные сеанса: http://news.php.net/php.internals/46999

Ответ 2

Как написано в цитате в вашем вопросе __PHP_Incomplete_Class_Name - это специальное имя класса в PHP, которое используется всякий раз, когда определение класса не может быть найдено при неэтериализации (unserialize()).

Он предложил либо обеспечить определение класса доступным, либо предоставить некоторую автозагрузку для отсутствующего класса.

Вы прокомментировали, что PHP ищет неправильное имя класса здесь:

wrong: LoginLogging
right: ScormElement

Трудно сказать с информацией, почему возникает имя класса при сериализации /unserialization. Информация, которую вы дали (особенно дамп) в своем вопросе, является неполной.

Таким образом, параметры ограничены некоторыми общими предложениями:

Вы можете проверить сериализованную строку, имя которой указано здесь, чтобы вы могли, по крайней мере, сказать, происходит ли это с сериализацией или безриализацией. Вы можете легко просмотреть сериализованные данные с помощью Сериализованной библиотеки PHP, которая имеет текстовый фьючерс для целей отладки.

Кроме того, существует unserialize_callback_func Ini-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
}

По мере того как вы пишете проблему больше не возникает, я подозреваю, что в какой-то момент сериализация на вашем сайте была нарушена, сохраняя неверные данные. Какую структуру/библиотеки/приложение вы используете? Какой компонент заботится о сериализации?

Ответ 3

Если вы пытаетесь получить доступ к методу свойства объекта или сериализованному значению, которое вы сохранили в переменной $_SESSION, и вы включили класс после вызова session_start(), попробуйте включить класс перед вызовом session_start();

Ответ 4

Возможно, вы используете какой-то кеш-код операции (например, APC, XCache) или какой-нибудь отладчик? Иногда они вызывают странные вещи. Если в вашем проекте нет и никогда не был классом LoginLogging, но ваш не единственный проект на сервере, я бы предлагал его в кеше.

Ответ 5

Это происходит, когда мы пытаемся инициализировать сеанс перед загрузкой определений классов для объекта, который мы пытаемся сохранить в сеансе.

вы можете использовать только json-методы в PHP

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

он будет работать уверенно.

Ответ 6

Чтобы включить класс до того, как session_start() работает отлично для меня. =)

Ответ 7

Когда вы пытаетесь выполнить переориентирование переменной, php должен знать структуру объекта. Попытайтесь включить свой класс перед unserialize. Какой класс? тот, который содержит эти свойства, показанные в вашем коде. include ('pathtoyourclass/classname.php') или include_once ('pathtoyourclass/classname.php').

Удачи!

Ответ 8

Это проблема сериализации в вашем коде. Возможно, ваш код по какой-то причине не смог инициализировать объект, а в следующей части кода пытается преобразовать этот объект в строку или какой-либо другой тип данных.

Просто проверьте свой код, правильно инициализируйте свои объекты.

Проверьте, используется ли метод serialize()/unserialize().

Ответ 9

Получаете ли вы этот сериализованный объект из службы/потока или читаете его из файла? Я видел, как это происходит на клиент-серверном уровне, когда клиентский объект и объекты на стороне сервера отличаются очень немного... возможно, есть свойство, которого нет у другого. Это также происходит, когда вы сериализуете объект, сохраняете его в файле, а затем код рефакторинга, который удаляет класс, а затем пытается десериализовать объект.

Затем, когда он десериализуется и пытается создать экземпляры необходимых классов, их не существует.

Ошибка ясна и проста, вы создаете объект, для которого класс не был загружен.

Я бы выполнил строковый поиск в вашем коде, нашел, где находится нужный класс, и сделайте простой автозагрузчик (или просто необработанный include/require) этого файла. Просто получите класс, который он должен загрузить как-то.

Если класс действительно нигде не существует, попробуйте проверить более ранние версии (я предполагаю, что у вас есть контроль версий какого-либо типа) для существования класса. Если вы десериализуете объект, сгенерированный другой системой, проверьте также, что система.

Ответ 10

Я использую эту функцию для решения этой проблемы

$user = $_SESSION['login'];
$auth_user= fixObject($user);
function fixObject(&$object) {
   if (!is_object($object) && gettype($object) == 'object')
      return ($object = unserialize(serialize($object)));
   return $object;
}