HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

クラスが定義されるタイミング

あるとき(何時)、聞かれたことに即答できなくて悔しかったのでちゃんと調べて書いてみる。
聞かれたことというのは、「1つのPHPファイルの中で、クラス定義とそれへの参照(new)の記述の前後によって動作が変わるか否か」。
冷静に考えれば、後ろのほうに書いてある関数を前のほうで呼び出したりしていたのだから、当然答えは「変わらない」になるのだが‥
ついでなので、includeする場合も一緒に並べてみた。
今回作成したPHPソースファイルは3つ。

  • class.php:クラス定義とinclude_once文のセットが2つ、そして、それぞれの前後にクラス定義がされているかどうかを出力する関数の呼び出し。
  • _class1.php:include_onceによって参照されるクラス定義の1つ目。
  • _class2.php:include_onceによって参照されるクラス定義の2つ目。

実際のソースは次のとおり。

<?php
ini_set('display_errors', 'On');

function printClassExists($no) {
    $clsNames = array('Hoge', 'Foo', 'Bar', 'Hoe');
    print("<pre>");
    print("=== {$no} ===\n");
    foreach ($clsNames as $clsName) {
        if (class_exists($clsName)) {
            printf("%-8s: O\n", $clsName);
        } else {
            printf("%-8s: X\n", $clsName);
        }
    }
    print("</pre>");
}

printClassExists(1);

include_once('./_class1.php');  // defines class Bar
class Hoge {
    function __construct() {
        print('Hoge'."\n");
    }
}

printClassExists(2);

class Foo {
    function __construct() {
        print('Foo'."\n");
    }
}
include_once('./_class2.php');  // defines class Hoe

printClassExists(3);
?>
<?php
class Bar {
    function __construct() {
        print('Bar'."\n");
    }
}
?>
<?php
class Hoe {
    function __construct() {
        print('Hoe'."\n");
    }
}
?>

実行結果は次のとおり。

=== 1 ===
Hoge    : O
Foo     : O
Bar     : X
Hoe     : X
=== 2 ===
Hoge    : O
Foo     : O
Bar     : O
Hoe     : X
=== 3 ===
Hoge    : O
Foo     : O
Bar     : O
Hoe     : O

class.php内で定義されているクラスはソースのどこでも参照することができる。一方、includeされるクラス定義は、実際にinclude文が呼ばれるまでは参照できない。
まぁ、そうだよね、という(謎)。