Menu

PHPのincludeとrequire:ほかのPHPファイルを読み込む

include 'header.php';は、そのコードを貼り付けたかのように、その場所でほかのPHPファイルを実行します。requireも同じことをしますが、ファイルがないと致命的エラーでスクリプトを止め、includeは警告を出して処理を続けます。include_onceとrequire_onceはファイルを最初の1回だけ読み込みます。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

include 'header.php';は、スクリプトのその場所で、貼り付けたかのようにほかのPHPファイルのコードを実行します。require 'header.php';も同じことをしますが、ファイルを読み込めないとき、requireは致命的エラーでスクリプトを止め、includeは警告を表示するだけで続けます。最初によく使うのは、すべてのページで共有するヘッダーとフッターです。

このブロックは、includeするファイルがあるよう先にheader.phpとfooter.phpを書き出します。実行してPageタブを見てください。

includeされるファイルは普通のPHPファイルです。<?= ?>タグを含むHTMLを書け、requireの前にセットした$title変数も見えます。タイトルを変えてもう一度実行してみてください。ヘッダーをrequireしているすべてのページが、その1つのファイルの変更を反映します。

includeとrequireの違い

違いは、ファイルがないか読めないときに何が起こるかだけです。includeは2つの警告を表示し、falseに評価され、スクリプトは続きます。

Warning: include(sidebar.php): Failed to open stream: No such file or directory in /home/index.php on line 2

Warning: include(): Failed opening 'sidebar.php' for inclusion (include_path='.:/usr/share/php83') in /home/index.php on line 2

requireは同じ警告を表示してからErrorを投げ、何かがキャッチしない限りスクリプトを終わらせます。

PHP Warning:  require(config.php): Failed to open stream: No such file or directory in /home/index.php on line 2
PHP Fatal error:  Uncaught Error: Failed opening required 'config.php' (include_path='.:/usr/share/php83') in /home/index.php:2

そのため、ページがそれなしでは動かないもの(設定、関数ライブラリ、クラスのファイル)にはrequireを、任意の部分にはincludeを使います。正当に存在しないこともある部分は、警告に頼らず先に確認しましょう。

出力:

Spring sale: 20% off
banner.php included, include returned int(1)
sidebar.php not found, skipped

include_onceとrequire_once

関数やクラスを定義するファイルは1回しか読み込めません。関数がすでに存在するので、2回目の読み込みは致命的エラーになります。

Fatal error: Cannot redeclare greet() (previously declared in /home/helpers.php:2) in /home/helpers.php on line 2

これは、2つのファイルがそれぞれrequire 'helpers.php'したとたんに起こります。require_onceとinclude_onceは、どのファイルがすでに読み込まれたかを覚えていて、2回目は飛ばしてtrueを返します。

出力:

int(1)
bool(true)
bool(true)
Hello, Ada

何かを宣言するファイルには_onceの形を使い、2回以上出力したいテンプレートには普通のincludeを使います。Composerを使うプロジェクトではオートローダーがクラスのファイルを読み込んでくれるので、クラスのためのrequire_onceの呼び出しはほとんどなくなります。Composerを参照してください。

includeしたファイルから値を返す

includeしたファイルのトップレベルのreturnは、そのファイルを止め、includeやrequireの式に値を返します。これできれいな設定ファイルが作れます。グローバル変数はなく、好きな名前に代入する値があるだけです。

出力:

My Shop
shop
bool(false)

Laravelの設定ファイル(config/app.php、config/database.phpなど)はこの方法で動いています。

includeしたファイルの変数とスコープ

includeしたコードは、includeした行のスコープで実行されます。スクリプトのトップではすべてのグローバル変数が見え、関数の中ではその関数のローカル変数だけが見えます。2つ目のルールを使えば、小さなテンプレートレンダラーが作れます。テンプレートに見せるべき変数をちょうどローカル変数として持つ関数です。

Pageタブには、1つのテンプレートファイルから描画された両方のリストが表示されます。includeはrender()の中で実行されるので、テンプレートには$headingと$productsが見えますが、$secretは見えません。テンプレートで使っているforeach ... endforeachの形は、PHPがHTMLテンプレート向けに用意している別の構文です。

includeのパスと__DIR__

'helper.php'のようなパスは、includeを含むファイルからの相対では解決されません。PHPはinclude_pathの設定(ふつうは現在の作業ディレクトリを表す.で始まります)を探し、そのあとでやっとincludeしているファイル自身のフォルダーを探します。そのためpartials/nav.phpの中のinclude 'helper.php'は、プロジェクトのルートにあるまったく別のhelper.phpを読み込むことがあります。現在のファイルのディレクトリを表す__DIR__を使えば、推測の余地がなくなります。

出力:

loaded the root helper.php
loaded partials/helper.php
__DIR__ in nav.php is partials

すべてのincludeを__DIR__ . '/relative/path.php'の形で書きましょう。作業ディレクトリはスクリプトの起動のされ方(Webサーバー、cronジョブ、別のフォルダーからのコマンドライン)によって変わりますが、__DIR__は決して変わりません。

ユーザーが名前を指定したファイルを決してincludeしない

最初のルーターによくあるのが、URLからページ名を読むinclude $_GET['page'] . '.php';です。これでは訪問者がサーバー上のどのファイルを実行するかを選べてしまいます。たとえば?page=../../config(ローカルファイルインクルージョン)で、古い設定ならほかのサーバーのファイルさえ選べます。代わりに、許可された名前をファイルに対応させましょう。ブロックを実行してリンクをクリックすると、クリックのたびに別の$_GET['page']でスクリプトがもう一度実行されます。

requireに届くのは$pagesにある3つの名前だけで、../secretのリンクは「Not found」のページになります。リクエストの値を安全に読む方法はGETと_GETと_POSTで扱っています。

よくある質問

PHPのincludeとrequireの違いは何ですか?

どちらもほかのPHPファイルを読み込んで実行します。ファイルを読み込めないとき、requireは致命的エラーでスクリプトを止め、includeは警告を表示してfalseを返し、スクリプトを続けます。設定や関数ライブラリのように、ページがそれなしでは動かないファイルにはrequireを使います。

requireではなくrequire_onceを使うべきなのはどんなときですか?

関数、クラス、定数を定義するファイルにはrequire_onceを使います。そのようなファイルを2回読み込むと致命的エラー(Cannot redeclare)になりますが、require_onceはすでに読み込んだファイルを飛ばします。何度も出力したいテンプレートには普通のincludeを使います。

includeしたPHPファイルは値を返せますか?

返せます。includeしたファイルのトップレベルのreturnはそのファイルを終わらせ、includeやrequireの式の値になります:config.phpにreturn ['debug' => true];と書いて$config = require 'config.php';とします。returnがなければ、includeの値は1です。

includeしたファイルから自分の変数にアクセスできますか?

できます。includeしたコードは、includeした行のスコープで実行されます。スクリプトのトップではグローバル変数が見え、関数の中ではその関数のローカル変数だけが見えます。そのファイルが作った変数も同じスコープに置かれます。

include('file.php')とinclude 'file.php'のどちらで書くべきですか?

どちらも動きます。includeとrequireは関数ではなく言語構造なので、括弧はパスを囲んでいるだけです。ほとんどのスタイルガイドは括弧なしでrequire 'file.php';と書きます。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める