同僚にPHPの質問をされて、あれって思って調べてみたら僕の思ったrequire
の動作とは違ったので、それを記事にして皆さんにお伝えします。
まず、以下のコードが実行できない。
- test.php
- req1.php
- req2.php
という3つのPHPファイルがあります。
<?php
ini_set('display_errors', "On");
require 'req1.php';
require 'req2.php';
echo 'hello<br>';
echo sayHello();
echo sayHello2();
<?php
require 'req2.php';
function sayHello() {
return "called sayHello<br>" . sayHello2();
}
<?php
function sayHello2() {
return "called sayHello2!<br>";
}
ここで重要なのは、req2.php
をrequire
しているのはtest.php
とreq1.php
の2つのPHPファイルだということです。
これを実行してみると、以下のエラーが出ます。
Fatal error: Cannot redeclare sayHello2() (previously declared in /xxxxxx/test.php:4) in /xxxxxx/req2.php on line 5
どうやら、sayHello2
が複数回宣言されているためエラーしているようです。ですが、複数回sayHello2
を宣言した覚えはありません!
原因は、requireにあった
まず、test.php
はreq1.php
とreq2.php
をrequireすることで、以下のように変換されるはずです。
<?php
ini_set('display_errors', "On");
//require 'req1.php';
require 'req2.php';
function sayHello() {
return "called sayHello<br>" . sayHello2();
}
//require 'req2.php';
function sayHello2() {
return "called sayHello2!<br>";
}
echo 'hello<br>';
echo sayHello();
echo sayHello2();
この状態ではまだrequire 'req2.php';
が残っているので、それもrequireすると、
<?php
ini_set('display_errors', "On");
//require 'req1.php';
//require 'req2.php';
function sayHello2() {
return "called sayHello2!<br>";
}
function sayHello() {
return "called sayHello<br>" . sayHello2();
}
//require 'req2.php';
function sayHello2() {
return "called sayHello2!<br>";
}
echo 'hello<br>';
echo sayHello();
echo sayHello2();
といった状態になるはずです。こうしてみると、test.php
内にsayHello2
関数が2つも宣言されていますね。これではエラーするのも当然です。
require_onceを使えば解決
ではどうやってこの問題を解決すればいいかと言いますと、require_onceを使って一度だけしかPHPファイルを読み込めないようにします。
<?php
ini_set('display_errors', "On");
require_once 'req1.php';
require_once 'req2.php';
echo 'hello<br>';
echo sayHello();
echo sayHello2();
<?php
require_once 'req2.php';
function sayHello() {
return "called sayHello<br>" . sayHello2();
}
<?php
function sayHello2() {
return "called sayHello2!<br>";
}
としてtest.php
を実行してみるとエラーなく実行されて、以下のように表示されます。
hello
called sayHello
called sayHello2!
called sayHello2!
require_onceがうまくいく理由
先ほどのように、require_onceした時にPHPの文がどのように展開されるかを見れば理解できると思います。
まず、test.php
はreq1.php
とreq2.php
をrequireします。
<?php
ini_set('display_errors', "On");
//require_once 'req1.php';
require_once 'req2.php';
function sayHello() {
return "called sayHello<br>" . sayHello2();
}
//require_once 'req2.php';
function sayHello2() {
return "called sayHello2!<br>";
}
echo 'hello<br>';
echo sayHello();
echo sayHello2();
で、この次にrequire_once 'req2.php';
が実行されると思いきや、既にreq2.php
はrequire
済みなので再度読み込みはしません。
よって、sayHello2
関数は一回だけしか宣言されないのでこのプログラムは正しく実行できます!
結論
require_once
を使いましょう!