当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func? [英] Why is unserialize_callback_func needed when spl_autoload_register is already used?

查看:79
本文介绍了当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 using spl_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 when spl_autoload_register is used.

          我认为在这里,我已经回答了这个问题?但是我会发布一些其他测试,只是为了好玩^^


          现在,如果我们尝试使用unserialize_callback_func而不使用spl_autoload_register怎么办?
          我想,代码看起来像他的:


          Now, what if we try using unserialize_callback_func, and not using spl_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 via unserialize_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
              • 设置名为callback_no_spl的自动加载功能
              • 并使用spl_autoload_register
              • 设置另一个名为callback_spl的自动加载功能.
              • Setting an autoload function, called callback_no_spl, with unserialize_callback_func
              • And setting another autoload function, called callback_spl, with 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中注册的自动加载功能
              • 它确实加载了包含类定义的文件
              • 并且数据已正确地反序列化.
              • 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 with unserialize_callback_func.


              我还能测试什么?
              哦,让我们测试一下设置这两个自动加载功能,但已将其注册为spl_autoload_register (即优先级最高的一个)实际上并未加载类的定义:


              What else can I test ?
              Oh, let's test setting both autoloading functions, but have the one registered by spl_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 :

                      • 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 of unserialize_callback_func...

                      这篇关于当已经使用了spl_autoload_register时,为什么需要unserialize_callback_func?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆