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


Object not being destroyed until end of the script if it registers spl_autoload_register();

对象在脚本结束前没有被销毁,有人能解释一下为什么使用spl_autoload_register()可以防止对象在unset()时被销毁吗?

只要没有对特定对象的其他引用,或者在关闭序列中按任何顺序调用析构函数方法。

spl_autoload_register()是否引用了注册它的对象,或者发生了什么?

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

spl_autoload_register()是否引用了注册它的对象,或者发生了什么?

是的,它有。但是,并不是因为spl_autoload_register在类内被调用。这是因为你的Closure

请参阅手册:

从PHP 5.4.0开始,当在类的上下文中声明时,当前类会自动绑定到它,使$this在函数的作用域中可用。如果不需要当前类的这种自动绑定,则可以使用静态匿名函数。

closure在类中创建时,它将自动绑定伪变量$this。那么你的实例将有两个引用:

  • $MyAutoLoader变量;
  • Closure传递给spl_autoload_register .

我重写了你的例子,有一些不同,你可以看到的行为:

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/>';

,结果将是:

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

在最后一个示例中,Closure是在类作用域之外创建的。所以只有变量$MyAutoLoader2拥有类的实例。

另一个可能的例子是:

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/>';

在最后一个示例中,我在类的外部创建Closure,但是我将类作用域绑定到类中,创建对MyAutoLoader类的新引用。结果将是:

End of script
Destroying: MyAutoLoader 

bindbindTo的更多提示,您可以在下面的链接中阅读:

如何调用一个包含了$this闭包的ReflectionFunction ?