【PHP】Fatal error: Cannot redeclare f() エラーの原因と対処(複数)

Fatal error: Cannot redeclare ...エラーの原因と対応方法について解説します。エラーメッセージの例は以下の通りです。

<?php
function f() {}
function f() {} // Fatal error: Cannot redeclare f() (previously declared in main.php:2) in main.php on line 3

エラーの原因は、同じ名前の関数が複数回定義されてしまっていることです。このようなエラーに繋がる要因は複数あり、要因別に適切な対処が必要となります。

原因と要因

対応と対策

スポンサーリンク
スポンサーリンク

include/require文による多重定義

include文やrequire文で同一のファイルを複数回読み込んでしまった場合に、関数の多重定義が発生してしまう恐れがあります。この場合は# include_once/require_once文による対策が有効です。

/* main.php */
<?php
require('f.php');
require('f.php'); // Fatal error: Cannot redeclare f() (previously declared in f.php:2) in f.php on line 2

/* f.php */
<?php
function f() {}

外部ファイルの関数と名前競合が発生した

include文やrequire文で読み込んだ関数が定義済みの関数だった場合にもエラーが発生します。この場合は# 定義済み関数のチェックによる対応が必要となります。

/* main.php */
<?php
function f() {}
include('f.php'); // Fatal error: Cannot redeclare f() (previously declared in main.php:2) in main.php on line 2

/* f.php */
<?php
function f() {}

入れ子関数の多重定義が発生した

入れ子関数を定義した際にも、同様のエラーが発生する恐れがあります。この場合は# 無名関数による多重定義の回避が有効な対応策です。

<?php
function main() { function f() {} }
main();
main(); // Fatal error: Cannot redeclare f() (previously declared in main.php:2) in main.php on line 2

include_once/require_once文による対策

include文やrequire文によるファイル読み込みの際にエラーが発生する場合は、include_once命令やrequire_once文を用いて対処する必要があります。

<?php
require('f.php');
require_once('f.php'); // 既に読み込まれているため無効

include_once命令やrequire_once文は、既に読み込まれているファイルを読み込まないという特性があるため、多重定義の問題を回避することにも繋がります。

こちらの方法で対処できないケースだった場合には、次項を参考にしてください。

定義済み関数のチェックによる対応

# include_once/require_once文による対策」や「# 無名関数による多重定義の回避」で対処できないケースの場合は、function_exists関数による定義済み関数のチェックが必要となります。

/* main.php */
<?php
function f() {}
if (!function_exists('f')) { // 関数`f`が定義されているかどうか
   function f() {} // 関数`f`が未定義の場合のみ実行/定義される
}

外部ファイル側でエラーが発生するケースでは、外部ファイル側での対応が必要となる点に注意が必要です。

/* main.php */
function f() {}
include('a.php');
include('b.php');

/* a.php */
<?php if (!function_exists('f')) { function f() {} }
/* b.php */
<?php if (!function_exists('f')) { function f() {} }

無名関数による多重定義の回避

関数内で入れ子状態の関数を定義するよりも、無名関数を用いたほうが安全です。無名関数は関数内のスコープでのみ有効な局所的な関数となるため、入れ子関数よりも厳格で安全となります。

ただし、PHP 5.3.0よりも古いバージョンのPHPでは無名関数を利用することができないため、# 定義済み関数のチェックによる対応が必要になります。
<?php
function main() {
   $f = function() {}; // 無名関数の定義
   $f();               // 無名関数の呼び出し
}

main();
main();
f();  // Fatal error(グローバル汚染も発生しないためより厳格)
$f(); // Fatal error
広告