PHPスクリプトが直接起動されたかどうかで処理を振り分ける

PHPスクリプトが直接起動されたかどうかで処理を振り分ける

スクリプトが直接呼び出された(=ブラウザから直接指定された)か、モジュールとして読み込まれたかで処理を振り分けたい、などということは頻繁にはありませんが、プログラマーの人生の中で一度か二度くらいはあるのではないでしょうか?

Javaだと各モジュールのmainメソッドに、そのモジュールをテストするコードを書いておいて、モジュールとして読み込まれるときは実行しない部分を記述しておくことができます。

class Test {
    public static void main(string[] args) {
        System.out.println("Hello, main method");
    }
}

これと同じことがPHPでできないかと思って調べてみました。

すると、スーパーグローバル変数の$_SERVER["SCRIPT_FILENAME"]と特殊な定数の__FILE__を比較することで、実現できるようです。以下の二つのスクリプトで実験してみました。

main.php

<?php
header('Content-Type: text/html; charset=EUC-JP');
header('Content-Language: ja');
echo "ブラウザから呼び出したスクリプト:" . realpath($_SERVER["SCRIPT_FILENAME"]) . "<br />";
echo "記述されているスクリプト:" . realpath(__FILE__) . "<br />";

if (realpath($_SERVER["SCRIPT_FILENAME"]) == realpath(__FILE__)){
    echo __FILE__ . ":<strong>直接スクリプトが起動されました</strong><br />";
} else {
    echo __FILE__ . ":<strong>モジュールとして読み込まれました。</strong><br />";
}
echo "<br />";
require_once("require.php");
?>

require.php

<?php
echo "ブラウザから呼び出したスクリプト:" . realpath($_SERVER["SCRIPT_FILENAME"]) . "<br />";
echo "記述されているスクリプト:" . realpath(__FILE__) . "<br />";

if (realpath($_SERVER["SCRIPT_FILENAME"]) == realpath(__FILE__)){
    echo __FILE__ . ":<strong>直接スクリプトが起動されました</strong><br />";
} else {
    echo __FILE__ . ":<strong>モジュールとして読み込まれました。</strong><br />";
}
echo "<br />";
?>

main.phpとrequire.phpは、main.phpでヘッダで文字コードの設定を送出し、require.phpをモジュールとして読み込んでいる他は同じ内容です。

そして、出力結果は以下のようになります。

ブラウザから呼び出したスクリプト:/home/projects/c-brains.jp/htdocs/main.php
記述されているスクリプト:/home/projects/c-brains.jp/htdocs/main.php
/home/projects/c-brains.jp/htdocs/main.php:直接スクリプトが起動されました

ブラウザから呼び出したスクリプト:/home/projects/c-brains.jp/htdocs/main.php
記述されているスクリプト:/home/projects/c-brains.jp/htdocs/require.php
/home/projects/c-brains.jp/htdocs/require.php:モジュールとして読み込まれました。

__FILE__定数の内容が、2つのスクリプトで変わることがわかります。つまり、

  • $_SERVER["SCRIPT_FILENAME"]は呼び出されたスクリプトの絶対パス
  • __FILE__は実際に命令文が実行される場所のスクリプトの絶対パス

がそれぞれ取得できるので、それで判別できるわけです。realpath関数でくくっているのは、古いバージョンでは__FILE__が相対パスを返すことがあるのでその予防です。

つまり、直接呼び出したときだけ実行したいブロックを定義したいときは、

if (realpath($_SERVER["SCRIPT_FILENAME"]) == realpath(__FILE__)){
    /** ここに処理を書いてね */
}

と書けばいいわけです。

PHPでのこういった書き方に何か名前が付いているかどうかはまだ知りませんので、ご存知の方がいたら教えてください。

Pythonのmainブロック

ちなみにPythonの場合はこうです。

if __name__ == '__main__':
    #ここに処理を書く

Javaにはmainメソッド、Pythonにはmainブロックという名前が付いています。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ