2010-02-24 2 views
3
ini_set('unserialize_callback_func', 'spl_autoload_call'); 

spl_autoload_register(array(self::getInstance(), 'autoload')); 

Зачем устанавливать spl_autoload_call, как указано выше?Почему unserialize_callback_func необходимо, когда spl_autoload_register уже используется?

Я сделал тест:

$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 

Может кто-нибудь объяснить это?

+0

Не могли бы вы ответить на этот вопрос, посмотрев код symfony? – VolkerK

+0

Да, я просматриваю код symfony, чтобы узнать, как он работает точно. Он получен из метода 'register' в sfCoreAutoload.class.php – user198729

ответ

-1

unserialize() требует определения класса, загруженного до фактической нессериализации данных. unserialize_callback_func вызывается, когда определение класса не загружается, и spl_autoload_call пытается использовать все автозагрузчики, зарегистрированные для загрузки класса, необходимого для unserialize().

+0

Не зарегистрированы ли функции, зарегистрированные в' spl_autoload_register' автоматически? – user198729

+0

Извините за downvote, но вопрос не в том, что делает 'unserialize_callback_func', но почему вы должны снова зарегистрировать отлично работающий автозагрузчик как unserialize_callback. – VolkerK

+0

Я ответил, когда вопрос был «Когда будет вызван spl_autoload_call?». Вот почему ответ странный. –

15

Я сделал несколько тестов, и здесь ноты, которые я взял (надеюсь, это будет понятно ^^ ;; и что я не получил слишком потерял в моей собственной мысли ^^)
Примечание: Я провел тесты на 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 не Neede d, когда используется 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); 

На этот раз, вот Ouput мы получаем:

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, не загрузила то, что она должна была иметь ...

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


Я предполагаю, что это странно поведение связано с тем, что:

«стек/очередь» поведение spl_autoload_register, я полагаю, может иметь некоторые помехи со старым поведением unserialize_callback_func ...

+1

+1 Удивительный ответ, спасибо Паскаль Мартин – Michael

+0

Ух ... TL, DR определенно необходим! –

Смежные вопросы