【PHP】requireとrequire_onceの違いと使い分けは?
PHPで別ファイルに定義した変数やコードを取り込むための関数として、require
命令と`require_onceが命令あります。
両者の動作の違いについて説明した記事はよく見かけますが、使い分けまで踏み込んだ記事は見つけられなかったため、少し調べてみました。
- 2021.09.03 初版公開
- 2021.09.09 追記
- 2021.10.12 改題
require
とrequire_once
の違い
公式ドキュメントでは、include_once
の項目で、これらの違いについて触れられています。
include_once命令は、スクリプトの実行時に指定したファイルを読み込み評価します。この動作は、
include
命令と似ていますが、ファイルからのコードが既に読み込まれている場合は、再度読み込まれないという重要な違いがあります。
(略)include_once
は、スクリプトの実行時にファイルが複数回読み込まれ、評価される可能性がある場合に、関数の再定義や変数値の再代入といった問題を回避するために一回だけ読み込ませるために使用します。
これによると、require_once
を使えば、同じファイルを複数回requireすることがなくなることがわかります。
そのため、関数の再定義や変数値の再代入が起こるといろいろと困る場面のほうが多いはずなので、普通に使うのであれば、require_once
を使ったほうがよさそうです。
逆に、require
が必要な場面ってあるのでしょうか?
reqire
とrequire_once
の動作を確認してみる
ここで、次のようなファイルを用意し、これをrequire
とrequire_once
でそれぞれ2回取り込んでみます。
$a = "Hello, world\n";
require
版のコード
require 'test.php';
print $a;
$a = "Hello, PHP\n";
require 'test.php';
print $a;
実行結果
Hello, world
Hello, world
require_once
版のコード
require_once 'test.php';
print $a;
$a = "Hello, PHP\n";
require_once 'test.php';
print $a;
実行結果
Hello, world
Hello, PHP
このように、requie_once
を使うと、2度目の読み込みが行われていないことがわかります。
関数等の定義がある場合
さらにrequire
について実験してみます。
function f($s)
{
print $s;
}
require 'test.php';
require 'test.php';
実行結果
PHP Fatal error: Cannot redeclare f() (previously declared in E:\home\work\php\work\test.php:xx) in E:\home\work\php\work\test.php on line yy
Fatal error: Cannot redeclare f() (previously declared in E:\home\work\php\work\test.php:xx) in E:\home\work\php\work\test.php on line yy
このように再定義されているとして致命的エラーが発生します。さらに、
require "test4.php";
require "test3.php";
require 'test3.php';
などとすると、延々と読み込み続けてしまいます。複数のファイルをrequireしていると、知らないうちにネストしていたということもありそうです。
こうやってみてみると、同じファイルを複数回読み込むメリットがあまり見出せません。
どういうときにrequire
を使うのがよいのでしょうか?
動作速度の違い?
Twitter上で「require_once
のほうがファイルを読み込んだかチェックする分動作が遅い」とのコメントを見ました。大規模なプロジェクトでは多数のファイルの読み込みが行われることもあると思いますので、どれくらい違うのか、試しに実験してみました。
実験
for($i = 0; $i < 1000; $i++>) {
require "test".$1.".php";
}
for($i = 0; $i < 1000; $i++>) {
require_once "test".$1.".php";
}
あらかじめtest0.php
~test999.php
までの空のファイルを作成しておいてから、このブログのサーバーを動かしているさくらVPS上でコマンドラインから上記のファイルを動かして実験しました。時間の計測にはtime
コマンドを使い、計測時間の変動を考慮して10回の平均をとって評価しました。
平均値(ms) | 最大値(ms) | 最小値(ms) | |
---|---|---|---|
require | 0.054 | 0.053 | 0.056 |
require_once | 0.055 | 0.054 | 0.057 |
1000個ファイル読み込む処理をしてみたところ、あまり変わらない結果となりました。ファイル名のチェックだけだったら、1回あたりの処理にそれほど時間がかからないのかもしれません。
動的生成されたファイルを読み込む
require
を使う場面があまり思いつかなかったのですが、上の実験を行っている最中にファイルを外部で生成するのであれば、複数回読み込めることにメリットがあることに気づきました。
例えば、外部のファイルを読み込んでパラメータを格納する変数を更新するような場合です。この場合も、PHPの主な使用方法であるWebアプリケーションというよりもコマンドラインからスクリプトとして使うようなイメージになると思いますので、この目的の出番は多くなさそうです。
定型文的なHTMLを読み込む(2021.09.09追記)
最終的にこの使い方が一番多そうな気がしてきました。HTMLをパーツに分けて、PHPのコード中に埋め込むような書き方をする場合、HTML取り込みの部分でrequire
, require_once
を使うことになります(もちろんinclude
, include_once
でも構わない)。この時、閉じタグなどは同じようなパターンで出現することが多いので、require_once
では取り込むことができません。require
が必要となってきます。
取り込むHTMLが定型的で何度も出現するような場合は、require
の恩恵が大きくなると言えます。
<div class="container">
<section>
</section>
</div>
$name = "izadori";
require "section_begin.php";
echo "<h1>Hello, World</h1>"
require "secition_end.php";
require "section_begin.php";
echo <<<EOF
<h1>Hello, $name</h1>
<h2>Menu</h2>
:
EOF;
require "secition_end.php";
まとめ
require
とrequire_once
の違いと使い分け方法は以下と考えられます。
require_once
はそのソースコード中で一度だけ読み込む。- 関数やクラスの定義がある場合はこちらを使う。
require
はソースコード中で実行されるたびに読み込みなおす。- 関数やクラスは重複定義となるため、致命的エラーとなる。
- 変数は読み込んだ値に上書きされる。
- 再帰的な読み込み方をしないように注意する必要がある。
- 動的に生成するような変数のみが記述されたファイルや、定型文的なHTMLを読み込むのに適している。
通常の使い方だとほぼrequire_once
で困らないかと思います。
UdemyやYouTubeでおなじみ「ともすた(たにぐちまこと)」さんの著書です。
ディスカッション
コメント一覧
まだ、コメントがありません