douzhechi2435 2016-10-31 18:59
浏览 97

如果对象注册了spl_autoload_register(),则在脚本结束之前不会销毁对象;

Object not being destroyed before script ends can someone explain why using spl_autoload_register() prevents object from destruction when unset().

The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.

Does spl_autoload_register() have reference to the object that registered it or what happens?

class MyAutoLoader {

    public function registerAutoLoader() {

        spl_autoload_register(function ($class) {

        });

    }

    public function __destruct() {
        echo 'Destroying: ' . get_class($this) . "<br/>";
    }

}

$MyAutoLoader = new MyAutoLoader();

$MyAutoLoader->registerAutoLoader();

unset($MyAutoLoader);

echo 'End of script<br/>';

//End of script
//Destroying: MyAutoLoader
  • 写回答

1条回答 默认 最新

  • doufangzhang4454 2017-01-04 11:22
    关注

    Does spl_autoload_register() have reference to the object that registered it or what happens?

    Yes, it does. But, doesn't because spl_autoload_register was called inside the class. That's happening because of your Closure.

    As you can read in manual:

    As of PHP 5.4.0, when declared in the context of a class, the current class is automatically bound to it, making $this available inside of the function's scope. If this automatic binding of the current class is not wanted, then static anonymous functions may be used instead.

    When the closure has been created inside the class, it'll bound automatically the pseudo-variable $this. Then your instance will have two references:

    • $MyAutoLoader variable;
    • Closure passed to spl_autoload_register.

    I've rewritten your example with a few differences which you can see the behavior:

    class MyAutoLoader {
    
        private $instance = "Outside";
    
        public function registerAutoLoader(Closure $closure = null) {
    
            //If a closure ins't passed as parameter, a new one will be created
            if (!$closure instanceof Closure)
            {
                $this->instance = "Inside";
                //A closure created inside a class will bound the pseudo-variable $this
                $closure = function ($class) {};
            }
    
            spl_autoload_register($closure);
    
        }
    
        public function __destruct() {
            printf('Destroying: %s - %s instance<br/>' , get_class($this) , $this->instance);
        }
    
    }
    
    $MyAutoLoader = new MyAutoLoader();
    $MyAutoLoader->registerAutoLoader();
    
    $MyAutoLoader2 = new MyAutoLoader();
    
    //A closure created outside of a class doesn't have the class scope
    $MyAutoLoader2->registerAutoLoader(function($class){});
    
    unset($MyAutoLoader , $MyAutoLoader2);
    
    echo 'End of script<br/>';
    

    And the result will be:

    Destroying: MyAutoLoader - Outside the instance
    End of script
    Destroying: MyAutoLoader - Inside the instance
    

    In the last example, the Closure has been created out of the class scope. So only the variable $MyAutoLoader2 has the instance of the class.

    Another possible example can be:

    class MyAutoLoader {
    
        public function registerAutoLoader(Closure $closure) {
    
            //Binding the class scope to the closure
            $closure = $closure->bindTo($this);
    
            spl_autoload_register($closure);
    
        }
    
        public function __destruct() {
            printf('Destroying: %s <br/>' , get_class($this));
        }
    
    }
    
    $MyAutoLoader = new MyAutoLoader();
    $MyAutoLoader->registerAutoLoader(function($class){});
    unset($MyAutoLoader);
    
    echo 'End of script<br/>';
    

    In this last example, I'm creating the Closure outside of class, but I'm binding the class scope into the class, creating a new reference to MyAutoLoader class. The result will be:

    End of script
    Destroying: MyAutoLoader 
    

    A few more tips from bind and bindTo you can read at the link below:

    How can I invoke a ReflectionFunction wrapping a closure that utilizes $this?

    评论

报告相同问题?

悬赏问题

  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题