PHP 7.4.0 以降では、エンジンの起動時に opcache に事前ロードするスクリプトを指定できるようになりました。 指定されたファイルに存在するあらゆる 関数、クラス、 インターフェイス や トレイト (定数は除く) は、 明示的にインクルードすることなく全てのリクエストからグローバルに利用できるようになります。 これにより(コードが常に利用できるようになるため)、メモリ使用量と、 パフォーマンスおよび便利さのトレードオフが発生します。 事前ロードされたスクリプトをクリアするには PHP プロセスの再起動が必要です。 つまり、この機能は本番環境でのみ役に立ちます。開発環境では役に立ちません。
パフォーマンスとメモリ使用量の最適なトレードオフは、アプリケーションによって異なることに注意して下さい。 "全てをあらかじめ読み込む" ことはもっとも簡単な戦略かもしれませんが、 必ずしも最適とは限りません。 さらに、コードの事前ロードは、リクエストが終了しても継続して生き残るプロセスの場合にだけ役に立ちます。 つまり、opcache が有効になった CLI スクリプトは動作はしますが、 一般的にコードの事前ロードは役に立ちません。 但し、FFI 経由でコードの事前ロードを使う場合は例外です。
注意:
コードの事前ロードは、Windows ではサポートされていません。
コードの事前ロードを設定するには、2つのステップが必要です。 まず、opcache を有効にしなければなりません。 その上で、opcache.preload の値を php.ini に設定します。
opcache.preload=preload.php
preload.php は、サーバの起動時(PHP-FPM, mod_php, など) に一度だけ実行され、リクエストを越えて生き残るメモリ領域に読み込まれる任意のファイルです。 PHP が root 権限で実行(推奨されません)される場合のために、 opcache.preload_user によって、事前ロードを実行するためのシステムユーザーを指定することが出来ます。 事前ロードを root で行うことは禁止されています。
preload.php スクリプトでは、
include,
include_once, require, require_once,
opcache_compile_file() で参照されるあらゆるファイルが評価され、
リクエストを越えて生き残るメモリ領域に読み込まれます。
次の例では、src ディレクトリにある全ての
.php ファイルが事前ロードされます。
但し、Test
ファイルの場合を除きます。
<?php
$directory = new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);
foreach ($phpFiles as $key => $file) {
require_once($file[0]);
}
?>
include と opcache_compile_file() 両方が動作しますが、コードをどう扱うかが異なります。
A
を定義しており、
b.php が A
を継承したクラス
B
を定義している場合、
opcache_compile_file() はそれらふたつのファイルを任意の順番で読み込めます。
しかし、include を使う場合、
a.php は 必ず 最初にインクルードしなければなりません。