脚本失去了魔术方法__destruct()的权限

Fir*_*One 4 php

我试图在对象实例化上创建一个文件,并在对象销毁时创建另一个文件.

这是代码:

class Foo{
    public function __construct(){
        file_put_contents('a_construct.txt', 'c');
    }
    public function __destruct(){
        file_put_contents('a_destruct.txt', 'd');
    }
}
Run Code Online (Sandbox Code Playgroud)

a_construct.txt通常会创建该文件.但是当涉及到创建a_destruct.txt文件时,它表现得非常奇怪.

如果我运行以下代码,则不会创建"a_destruct"文件.

$foo = new Foo();
Run Code Online (Sandbox Code Playgroud)

我收到这个错误:

警告: file_put_contents(a_destruct.txt):无法打开流:权限被拒绝


现在,如果我运行以下命令并检查文件夹,那么该文件就在那里.

$foo = new Foo();
unset($foo);
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

  • 将名称交换constructdestruct和返回,但它始终只适用于该__construct方法;
  • 在方法上添加输出以确认它们被调用 - 它们是(并且对于两个测试代码).

第二个测试代码显示我,我这样做有权限来创建一个文件.

但是第二个主题告诉我,当我在脚本结束时销毁对象时,我'失去'权限(因为我确保调用该方法).


造成这种情况的原因是什么以及如何解决?

Fir*_*One 5

修复它,您可以使用完整路径:

public function __destruct(){
    file_put_contents(dirname(__FILE__) . '/a_destruct.txt', 'd');
}
Run Code Online (Sandbox Code Playgroud)

这在手册中有记录:

脚本关闭阶段的工作目录可能与某些SAPI(例如Apache)不同.


这意味着您尝试在不同的目录中创建文件 - 以及您没有权限的目录.

这就是为什么它在你运行时有效unset($foo)- 因为它还没有处于关机阶段.


虽然我不建议在关机阶段弄乱工作目录,但我觉得这表明它是可能的:

public function __destruct(){
    $tmp = getcwd(); // get current working dir
    chdir(dirname(__FILE__)); // set it to be same as the file
    file_put_contents('a_destruct.txt', 'd');
    chdir($tmp); // set the working dir back to what it was before
}
Run Code Online (Sandbox Code Playgroud)