Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

register_shutdown_functionとオブジェクトメソッド


PEAR::Image_Graphvizのソース(Image/Graphviz.php)をいろいろいじっていたら、一時的に作成されたdotファイルや画像ファイルをunlinkしているであろう箇所をコメントアウトしても削除されてることに気づきました。
何でかな〜?と思い、ソースを追っかけてみると、PEARのコアパッケージであるSystemクラスの中でregister_shutdown_functionを使ってうまくやってたんですね。

<?php
class System
{function mktemp($args = null)
    {if ($first_time) {
            PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
            $first_time = false;
        }
        return $tmp;
    }

で、Systemクラスではstaticメソッドとして登録してますが、オブジェクトメソッドの場合どうなのか?そのオブジェクトが消された場合はどうなのか?気になりだしたので、以下の様なコードで実際に見てみました。

<?php
function doLog() {
    $logfile = '/tmp/register_shutdown_function.log';
    `LANG=C ls -al /tmp/data* /tmp/temporary* >> $logfile`;
    `LANG=C echo  "--------------" >> $logfile`;
}

class WorkFile {
    private $files;
    public function __construct() {
        $this->files = array();
        register_shutdown_function(array($this, 'cleanUp'));
    }
    public function create($filename) {
        $file = '/tmp/' . basename($filename);
        `touch $file`;
        $this->files[] = $file;
    }
    public function cleanUp() {
        foreach ($this->files as $target_file) {
            unlink($target_file);
        }
    }
}
$work = new WorkFile();
$work->create('data');
$work->create('temporary');

doLog();

$work2 = new WorkFile();
$work2->create('data2');
$work2->create('temporary2');

doLog();

$work = null;
$work2 = null;

doLog();

結果は、

ちゃんとファイルが削除された

つまり登録したシャットダウン関数が実行されてる時は「$this」ってまだ生きてるんですね。というか、register_shutdown_function関数をコールした後にオブジェクト変数を更新している(createメソッド)のに、ちゃんと保持してたのがちょっとだけ感動。当然?