Help us understand the problem. What is going on with this article?

PHPの実行時とコンパイル時

More than 5 years have passed since last update.

PHPはプログラムの実行前にソースコードをコンパイルするんだよ、ってことを雑に書いた。

函数定義はコンパイル時に

単純にソースコードを上から順に実行してるだけではないことは次の例で確認できます。

hello.php
<?php
echo hello(), PHP_EOL; // hello()の定義はexitの下にある
exit; //ここで処理は終了する

echo "a", PHP_EOL; // この行は実行されない

function hello()
{
    return "Hello!";
}

echo "b", PHP_EOL; // この行は実行されない
結果
Hello!

次の例も見てみませう。

hello2.php
<?php
echo "1", PHP_EOL;

function hello()
{
    return "Hello! 1";
}

echo "2", PHP_EOL;

function hello() // 同名の函数は定義できない
{
    return "Hello! 2";
}
結果
Fatal error: Cannot redeclare hello() (previously declared in /home/jail/prog.php:7) in /home/jail/prog.php on line 15

Cannot redeclare hello()と怒られますが、12も出力されることはありません。

クラスの解決は実行時に

存在しないクラスを参照しようとしたり静的ではないメソッドを静的に呼ぼうとしても、怒られるのは実行時だ。

method.php
<?php
error_reporting(E_ALL | E_STRICT);
set_error_handler('error_handler');

$foo = new Foo;
echo Foo::bar(), PHP_EOL;

if (false) {
    echo Foo::Buz(), PHP_EOL; // メソッドを静的に呼び出そうとする
    $hoge = new Hoge;         // 存在しないクラスのインスタンス
    $hoge->fuga();            // 存在しないクラスの存在しないメソッド
    hoge_fuga();
}

echo $foo->buz(), PHP_EOL;
hoge_fuga(); // 存在しない函数を読んでみる

echo "Bye.", PHP_EOL; // ↑で止まるので、この行が出力されることはにあ

exit;

final class Foo
{
    public static function bar()
    {
        return "Foo::Bar!";
    }

    public function buz()
    {
        return "foo->Buz!";
    }
}

function error_handler($severity, $message, $file, $line) 
{
    throw new \ErrorException($message, 0, $severity, $file, $line);
}
結果
Foo::Bar!
foo->Buz!
Fatal error: Call to undefined function hoge_fuga() in /home/jail/prog.php on line 16

実行時にしか怒られないといふことは、if (false)の中身は実行されないので怒られない!

クラスローダー

PHPのクラスローダーは、実行時に未定義のクラスが登場したときに、初めてそのクラスが定義されたファイルを読み込もうとする仕組みだ。php.netのPHP: クラスのオートローディング - Manualも読まれたい。

今回は詳しい説明を省くが、Composerまたはtheseer/Autoloadを利用するのが良い。

$ tree .
.
└── src
    ├── Hoge
    │   └── Fuga.php
    ├── Hoge.php
    └── Piya.php

2 directories, 3 files

Autoload Builderは以下のようなPHPを生成する。

autoload.php
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
spl_autoload_register(
    function($class) {
        static $classes = null;
        if ($classes === null) {
            $classes = array(
                'zonuexe\\hoge' => '/src/Hoge.php',
                'zonuexe\\hoge\\fuga' => '/src/Hoge/Fuga.php',
                'zonuexe\\piyo' => '/src/Piya.php'
            );
        }
        $cn = strtolower($class);
        if (isset($classes[$cn])) {
            require __DIR__ . $classes[$cn];
        }
    },
    true,
    false
);
// @codeCoverageIgnoreEnd

このような仕組みを利用すれば、requireするタイミングを実行時に遅延できる。

最後に

「PHPはコンパイルしない言語」みたいな意味不明な発言はやめよう。

php hoge.phpのようにコマンドにソースコードのファイルを指定して直接実行してるように見えたとしても、現代的なインタプリタはソースコードをパースしたあと仮想機械バイトコードにコンパイルする。RubyもPythonもPerl5もEmacsも同様に。

では「PHPはネイティブコードにコンパイルしない」であれば正しいかといふと、Facebookの開発したHHVMでPHPを実行するとJITコンパイラによってネイティブコードにコンパイルされる。

もっと実装寄りの具体的な話を知りたい方は、ぜひPHP による hello world 入門 | 東北ギークといふ神記事をお読みください。

tadsan
僕に警備する自宅をください。Emacs初心者。Rubyist。 全ての投稿された記事は別段の表記がない限りはCC 3.0 BY-SA https://creativecommons.org/licenses/by-sa/3.0/deed.ja で二次利用できます。 記事中に含まれる全てのコードスニペットの著作権は抛棄するので、煮るなり焼くなりお好きにどうぞ。
https://tadsan.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした