当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func? [英] Why is unserialize_callback_func needed when spl_autoload_register is already used?
问题描述
ini_set('unserialize_callback_func', 'spl_autoload_call');
spl_autoload_register(array(self::getInstance(), 'autoload'));
为什么要像上面那样设置 spl_autoload_call
?
Why set spl_autoload_call
like above?
我做了一个测试:
$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上进行了测试.
I did some tests, and here are the notes I took (hope it'll be understandable ^^ ;; and that I didn't get too lost in my own thought ^^ )
Note : I've done my tests on PHP 5.3.2-dev, in case it matters.
首先,让我们定义一个temp-2.php
文件,该文件将仅包含以下内容:
First of all, let's define a temp-2.php
file, that's going to contain only this :
<?php
class a {
}
即与我们将尝试反序列化的对象相对应的类的定义.
i.e. the definition of the class that corresponds to the object we'll be trying to unserialize.
我将发布的代码的所有其他部分将包含在名为temp.php
的文件中-该文件必须包含temp-2.php
,以便知道类的定义.
And all other portions of code I will post will be contained in a file called temp.php
-- which would have to include temp-2.php
so the class' definition is known.
第一次尝试:我们尝试对字符串进行反序列化,而无需定义类a
:
First try : we try to unserialize the string, without having defined the class 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);
作为输出,我们得到了这个:
As output, we get this :
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
注册
- 但是它没有自动加载任何东西
- The autoloading function
callback_spl
has been called- even if registered by
spl_autoload_register
- But it has not autoloaded anything
现在,让我们尝试使用spl_autoload_register
注册一个自动加载功能,该功能实际上会自动加载该类的定义:
Now, let's try usingspl_autoload_register
to register an autoloading function that actually autoloads the class' definition :$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
注册的自动加载功能- 这一次,它确实需要包含类定义的文件
- The autoloading function registered by
spl_autoload_register
has been called- And, this time, it did require the file containing the definition of the class
- 即我们不再有
__PHP_Incomplete_Class
的实例 - 我们实际上得到了
a
的实例
- i.e. we don't get an instance of
__PHP_Incomplete_Class
anymore, - we actually get an instance of
a
因此,在这里,我要说的是,使用
spl_autoload_register
时不需要unserialize_callback_func
.So, here, I would say that
unserialize_callback_func
is not needed whenspl_autoload_register
is used.我认为在这里,我已经回答了这个问题?但是我会发布一些其他测试,只是为了好玩^^
现在,如果我们尝试使用unserialize_callback_func
而不使用spl_autoload_register
怎么办?
我想,代码看起来像他的:
Now, what if we try usingunserialize_callback_func
, and not usingspl_autoload_register
?
The code will look like his, I suppose :$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);
然后,作为输出,我们得到:
And, as output, we get :
string 'callback_no_spl : a' (length=19) object(a)[1] public 'value' => string '100' (length=3)
所以,一切正常:
- 通过
unserialize_callback_func
注册的callback_no_spl
回调函数被调用- 它将加载类的定义
- The
callback_no_spl
callback function registered viaunserialize_callback_func
is called- It loads the definition of the class
- 即我们得到一个
a
的实例
- i.e. we get an instance of
a
再往前走,让我们尝试一下当两者都可以得到的东西:
Going a bit farther, let's try what we can get when both :- 使用
unserialize_callback_func
设置名为 - 并使用
spl_autoload_register
设置另一个名为
callback_no_spl
的自动加载功能callback_spl
的自动加载功能.- Setting an autoload function, called
callback_no_spl
, withunserialize_callback_func
- And setting another autoload function, called
callback_spl
, withspl_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
中注册的自动加载功能 - 它确实加载了包含类定义的文件
- 并且数据已正确地反序列化.
- only the autoloading function registered with
spl_autoload_register
has been called - It did load the file that contains the class' definition
- And the data has been unserialized properly.
现在,只是为了好玩,如果我们尝试更改设置自动加载器的顺序,该怎么办?
即使用这部分代码:
Now, just for fun, what if we try changing the order in which we set the autoloaders ?
i.e. use this portion of code :$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);
我们得到与以前完全相同的输出:
We get exactly the same output as before :
string 'callback_spl : a' (length=16) object(a)[1] public 'value' => string '100' (length=3)
似乎表明,用
spl_autoload_register
定义的自动加载器的优先级高于用unserialize_callback_func
定义的自动加载器.Which seems to indicate that the autoloader defined with
spl_autoload_register
as a higher priority than the one defined withunserialize_callback_func
.
我还能测试什么?
哦,让我们测试一下设置这两个自动加载功能,但已将其注册为spl_autoload_register
(即优先级最高的一个)实际上并未加载类的定义:
What else can I test ?
Oh, let's test setting both autoloading functions, but have the one registered byspl_autoload_register
(i.e. the one with the highest priority) not actually load the class' definition :$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);
这一次,这是我们得到的输出:
This time, here's the ouput we get :
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
中注册的自动加载功能已被调用- 它没有加载类的定义
- The autoloading function registered with
spl_autoload_register
has been called- It did not load the class' definition
- 它确实加载了类的定义
- 因此,我们已经正确获得了未序列化的数据.
现在,让我们回到您发布的代码示例-转换为 my 函数名称,我想这会给我们这样的东西:
Now, let's come back to the code example you posted -- translated to my functions names, it would give us something like this, I suppose :$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);
而且,这次,我得到了与您相同的东西:
And, this time, I get the same kind of thing as you did :
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
中注册的功能称为- 并且不会加载类的定义
- The function registered with
spl_autoload_register
is called- And doesn't load the class' definition
- 它也不会加载类的定义...
- 它仍然不会加载类的定义
- 请注意,这仅在第二次调用
callback_spl
之后发生! - 这似乎表明即使使用
unserialize_callback_func
定义的函数没有加载应有的内容,也会发生某种自动加载的情况.
- Note this only happens after
callback_spl
has been called for the second time ! - Which seems to indicate that there is some kind of autoloading happening even if the function defined with
unserialize_callback_func
didn't load what it should have...
我必须承认,这既好又棘手-而且我也不知道为什么会这样,因为这似乎没有多大意义...
I have to admit, this is both nice and tricky -- and I have quite no idea why this is happening, as it doesn't seem to make much sense...
我认为这种奇怪行为与以下事实有关:
I suppose this strange behavior has to do with the fact that :-
自PHP以来,
-
unserialize_callback_func
存在4.2 - 而
spl_autoload_register
仅存在,因为PHP 5.1 并且PHP 5中引入了__autoload
>
unserialize_callback_func
exists since PHP 4.2- while
spl_autoload_register
only exists since PHP 5.1 and__autoload
has been introduced in PHP 5
我想
spl_autoload_register
的堆栈/队列"行为可能会干扰unserialize_callback_func
的旧行为...The "stack / queue" behavior of
spl_autoload_register
, I suppose, can have some interferences with the old behavior ofunserialize_callback_func
...这篇关于当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- even if registered by
- 即使已由