基底クラス PEARのデストラクタ[Pear]

Pearの基底クラスであるPEARクラスを読んでみます。

まず目に付くのがコンストラクタです。PHP4では、デストラクタがサポートされていません そのため、PEARのコンストラクタでは、スクリプト処理が完了した際に実行される 関数を 登録するregister_shutdown_functionを使ってデストラクタっぽく振舞うようにしています。

//PEARのコンストラクタ
while ($classname && strcasecmp($classname, "pear")) {
    $destructor = "_$classname";
    if (method_exists($this, $destructor)) {
        global $_PEAR_destructor_object_list;
        $_PEAR_destructor_object_list[] = &$this;
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
            register_shutdown_function("_PEAR_call_destructors");
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
        }
        break;
    } else {
        $classname = get_parent_class($classname);
    }
}

このソースから、デストラクタとして登録するには_(アンダースコア)+クラス名がデストラクタ になるようです。

method_exists関数によって対象となるクラスにデストラクタとして使用する関数が存在するか 確認しています。その後、対象となるクラスを$_PEAR_destructor_object_list[]に登録しています。

次にPEARのコンストラクタで登録されたregister_shutdown_function("_PEAR_call_destructors"); _PEAR_call_destructors関数を見てみます。

//PEARデストラクタ
while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
    $classname = get_class($objref);
    while ($classname) {
        $destructor = "_$classname";
        if (method_exists($objref, $destructor)) {
            $objref->$destructor();
            break;
        } else {
            $classname = get_parent_class($classname);
        }
    }
}

$_PEAR_destructor_object_listからオブジェクトを取得し、デストラクタとして登録された 関数を実行しています。

注意しないといけないのは、register_shutdown_functionは

  • スクリプト処理が完了した際に実行される
  • ブラウザへの出力は許可されない。 そのためprintまたはechoを使用してデバッグを行うことができない。