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
Может кто-нибудь объяснить это?
Я сделал несколько тестов, и вот заметки, которые я взял (надеюсь, это будет понятно ^^ ;; и что я не потерялся в своей собственной мысли ^^)
Примечание. Я провел тесты на 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
для регистрации функции автозагрузки, которая фактически автоматически 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
функция автозагрузки, зарегистрированная функцией spl_autoload_register
__PHP_Incomplete_Class
, Итак, здесь я бы сказал, что unserialize_callback_func
не требуется, когда используется spl_autoload_register
.
Я думаю, здесь, я как-то ответил на вопрос? Но я отправлю пару других тестов, просто для удовольствия ^^
Теперь, что, если мы попытаемся использовать unserialize_callback_func
и не spl_autoload_register
использовать 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
callback_no_spl, зарегистрированная через unserialize_callback_func
Отправляясь немного дальше, давайте попробуем то, что мы можем получить, когда оба:
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
функция автозагрузки, зарегистрированная с помощью 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
функция, зарегистрированная с помощью spl_autoload_register
unserialize_callback_func
spl_autoload_register
вызывается снова!
unserialize_callback_func
, не загружала определение класса
callback_spl
во второй раз! unserialize_callback_func
, не загрузила то, что она должна была иметь … Должен признаться, это так приятно и сложно – и я совершенно не понимаю, почему это происходит, поскольку это, похоже, не имеет большого смысла …
Я полагаю, что это странное поведение связано с тем, что:
unserialize_callback_func
существует с PHP 4.2 spl_autoload_register
существует только тогда, spl_autoload_register
PHP 5.1 и __autoload
были введены в PHP 5 Полагаю, что поведение «stack / queue» spl_autoload_register
может иметь некоторые помехи со старым поведением unserialize_callback_func
…
unserialize () требует, чтобы определение класса загружалось до фактического нессериализации данных. unserialize_callback_func вызывается, когда определение класса не загружается, и spl_autoload_call пытается использовать все автозагрузчики, зарегистрированные для загрузки класса, необходимого для unserialize ().