gpt4 book ai didi

php - 当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func?

转载 作者:可可西里 更新时间:2023-11-01 13:38:15 25 4
gpt4 key购买 nike

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注册一个自动加载功能,该功能实际上是自动加载该类的定义:
    $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.2以来就存在
  • ,而 spl_autoload_register 仅从PHP 5.1开始存在
    并且 __autoload 已在PHP 5中引入

  • 我想 spl_autoload_register的“堆栈/队列”行为可能会对 unserialize_callback_func的旧行为产生一些干扰...

    关于php - 当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2325884/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com