ini_set('unserialize_callback_func', 'spl_autoload_call'); spl_autoload_register(array(self::getInstance(), 'autoload'));
Почему установленный
spl_autoload_call
как вышеупомянутый?Я сделал тест:
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}'; ini_set('unserialize_callback_func','mycallback'); function mycallback($classname) { echo 1; } function func2() { echo 2; } spl_autoload_register('func2'); unserialize($serialized_object);
Вывод:
212
Кто-то может объяснить это?
unserialize () требует загрузки определения класса перед фактической десериализацией данных. unserialize_callback_func вызывается, когда определение класса не загружено, а spl_autoload_call пытается использовать все автозагрузчики, зарегистрированные для загрузки класса, необходимого для unserialize ().
Я провел несколько тестов, и вот записи, которые я сделал (надеюсь, они будут понятны ^^ ;; и что я не слишком заблудился в своих собственных мыслях ^^ )
Примечание: я провел свои тесты на PHP 5.3.2-dev, если это имеет значение.
Прежде всего, давайте определим файл temp-2.php
, который будет содержать только это :
<?php
class a {
}
т.е. определение класса, соответствующего объекту, который мы будем пытаться десериализовать.
А все остальные части кода, которые я буду размещать, будут содержаться в файле под названием temp.php
- который должен включать temp-2.php
, чтобы определение класса было известно.
Первая попытка: попробуем отсериализовать строку, не определив класс a
:
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
}
spl_autoload_register('callback_spl');
$data = unserialize($serialized_object);
var_dump($data);
На выходе получаем вот это :
string 'callback_spl : a' (length=16)
object(__PHP_Incomplete_Class)[1]
public '__PHP_Incomplete_Class_Name' => string 'a' (length=1)
public 'value' => string '100' (length=3)
Что означает, что :
callback_spl
spl_autoload_register
__PHP_Incomplete_Class
Теперь попробуем использовать spl_autoload_register
для регистрации функции автозагрузки, которая действительно автозагружает определение класса:
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
spl_autoload_register('callback_spl');
$data = unserialize($serialized_object);
var_dump($data);
И мы получаем вот такой результат :
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Что означает:
spl_autoload_register
, была вызвана.
__PHP_Incomplete_Class
, a
Таким образом, здесь я бы сказал, что unserialize_callback_func
не нужен, когда используется spl_autoload_register
.
Думаю, здесь я вроде бы ответил на вопрос? Но я опубликую еще пару тестов, просто для развлечения ^^
Теперь, что если мы попробуем использовать unserialize_callback_func
, и не использовать spl_autoload_register
?
Код будет выглядеть как он, я полагаю :
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
ini_set('unserialize_callback_func', 'callback_no_spl');
function callback_no_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
$data = unserialize($serialized_object);
var_dump($data);
И на выходе мы получаем :
string 'callback_no_spl : a' (length=19)
object(a)[1]
public 'value' => string '100' (length=3)
Итак, все работает нормально :
callback_no_spl
функция обратного вызова, зарегистрированная через unserialize_callback_func
a
Идя немного дальше, давайте попробуем, что мы можем получить, когда оба :
callback_no_spl
, с помощью unserialize_callback_func
callback_spl
, с помощью spl_autoload_register
Код будет выглядеть следующим образом:
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
ini_set('unserialize_callback_func', 'callback_no_spl');
function callback_no_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
spl_autoload_register('callback_spl');
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
$data = unserialize($serialized_object);
var_dump($data);
А на выходе мы получим :
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Что означает:
spl_autoload_register
Теперь, просто ради интереса, что если мы попробуем изменить порядок, в котором мы устанавливаем автозагрузчики?
т.е. использовать эту часть кода :
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
spl_autoload_register('callback_spl');
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
ini_set('unserialize_callback_func', 'callback_no_spl');
function callback_no_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
$data = unserialize($serialized_object);
var_dump($data);
Мы получим точно такой же результат, как и раньше :
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Что, похоже, указывает на то, что автозагрузчик, определенный через spl_autoload_register
, имеет более высокий приоритет, чем тот, который определен через unserialize_callback_func
.
Что еще можно проверить?
О, давайте протестируем установку обеих функций автозагрузки, но пусть та, что зарегистрирована spl_autoload_register
(т.е. та, что имеет наивысший приоритет) не загружает определение класса :
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
ini_set('unserialize_callback_func', 'callback_no_spl');
function callback_no_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
require dirname(__FILE__) . '/temp-2.php';
}
spl_autoload_register('callback_spl');
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
//require dirname(__FILE__) . '/temp-2.php'; // We don't load the class' definition
}
$data = unserialize($serialized_object);
var_dump($data);
На этот раз вот какой результат мы получим :
string 'callback_spl : a' (length=16)
string 'callback_no_spl : a' (length=19)
object(a)[1]
public 'value' => string '100' (length=3)
В основном :
spl_autoload_register
была вызвана.
unserialize_callback_func
Теперь вернемся к примеру кода, который вы опубликовали - переведенный в мои имена функций, он даст нам что-то вроде этого, я полагаю :
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';
ini_set('unserialize_callback_func', 'callback_no_spl');
function callback_no_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
//require dirname(__FILE__) . '/temp-2.php'; // We don't load the class' definition
}
spl_autoload_register('callback_spl');
function callback_spl($className) {
var_dump(__FUNCTION__ . ' : ' . $className);
//require dirname(__FILE__) . '/temp-2.php'; // We don't load the class' definition
}
$data = unserialize($serialized_object);
var_dump($data);
И, на этот раз, я получаю то же самое, что и вы :
string 'callback_spl : a' (length=16)
string 'callback_no_spl : a' (length=19)
string 'callback_spl : a' (length=16)
( ! ) Warning: unserialize() [function.unserialize]: Function callback_no_spl() hasn't defined the class it was called for ...
object(__PHP_Incomplete_Class)[1]
public '__PHP_Incomplete_Class_Name' => string 'a' (length=1)
public 'value' => string '100' (length=3)
И, на этот раз :
spl_autoload_register
unserialize_callback_func
spl_autoload_register
!
unserialize_callback_func
, не загрузила определение класса.
callback_spl
была вызвана во второй раз! unserialize_callback_func
, не загрузила то, что должна была... Должен признать, что это и приятно, и сложно - и я совершенно не представляю, почему это происходит, поскольку это не имеет особого смысла...
Я полагаю, что это странное поведение связано с тем, что :
unserialize_callback_func
существует с версии PHP 4.2spl_autoload_register
существует только с версии PHP 5.1
а __autoload
появился в PHP 5Поведение "стек / очередь" spl_autoload_register
, я полагаю, может иметь некоторые помехи со старым поведением unserialize_callback_func
...