use*_*729 5 php spl-autoload-call
ini_set('unserialize_callback_func', 'spl_autoload_call');
spl_autoload_register(array(self::getInstance(), 'autoload'));
Run Code Online (Sandbox Code Playgroud)
为什么设置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);
Run Code Online (Sandbox Code Playgroud)
输出是:
212
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下吗?
Pas*_*TIN 16
我做了一些测试,这里是我所做的笔记(希望它是可以理解的^^ ;;并且我不会在我自己的想法中迷失^^)
注意:我已经在PHP 5.3上完成了我的测试.2-dev,万一重要.
首先,让我们定义一个temp-2.php文件,它只包含这个:
<?php
class a {
}
Run Code Online (Sandbox Code Playgroud)
即对应于我们将尝试反序列化的对象的类的定义.
我将发布的代码的所有其他部分将包含在一个名为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);
Run Code Online (Sandbox Code Playgroud)
作为输出,我们得到这个:
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)
Run Code Online (Sandbox Code Playgroud)
意思就是 :
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);
Run Code Online (Sandbox Code Playgroud)
我们得到这个输出:
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Run Code Online (Sandbox Code Playgroud)
意思是 :
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);
Run Code Online (Sandbox Code Playgroud)
而且,作为输出,我们得到:
string 'callback_no_spl : a' (length=19)
object(a)[1]
public 'value' => string '100' (length=3)
Run Code Online (Sandbox Code Playgroud)
所以,一切正常:
callback_no_spl通过注册的回调函数unserialize_callback_func被调用
a
走得更远,让我们尝试两者兼得的结果:
callback_no_spl,用unserialize_callback_funccallback_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);
Run Code Online (Sandbox Code Playgroud)
我们得到的输出:
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Run Code Online (Sandbox Code Playgroud)
意思是 :
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);
Run Code Online (Sandbox Code Playgroud)
我们得到与以前完全相同的输出:
string 'callback_spl : a' (length=16)
object(a)[1]
public 'value' => string '100' (length=3)
Run Code Online (Sandbox Code Playgroud)
这似乎表明自动加载器定义的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);
Run Code Online (Sandbox Code Playgroud)
这一次,这是我们得到的输出:
string 'callback_spl : a' (length=16)
string 'callback_no_spl : a' (length=19)
object(a)[1]
public 'value' => string '100' (length=3)
Run Code Online (Sandbox Code Playgroud)
基本上:
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);
Run Code Online (Sandbox Code Playgroud)
而且,这一次,我得到了和你一样的东西:
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)
Run Code Online (Sandbox Code Playgroud)
而且,这一次:
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自PHP 5.1以来只存在并且__autoload已经在PHP 5中引入spl_autoload_register我想,"堆栈/队列"行为会对unserialize_callback_func...... 的旧行为产生一些干扰.
Sam*_*ark -1
unserialize() 需要在实际反序列化数据之前加载类定义。当未加载类定义并且 spl_autoload_call 尝试使用所有已注册的自动加载器来加载 unserialize() 所需的类时,将调用 unserialize_callback_func。