WordPressで「Fatal error: Cannot redeclare」と表示されるとき

WordPress個別サポート

WordPressでPHPの編集時に「Fatal error: Cannot redeclare …」と表示されて画面が真っ白(HTTP 500 エラー)になることがあります。ここでは、WordPressユーザーの目線から「Fatal error: Cannot redeclare …」が起きる理由や対処法を紹介していきます。

WordPressで「Fatal error: Cannot redeclare …」が起きる原因

「Fatal error: Cannot redeclare …」とは「関数が二重定義になっているため処理を停止する」という意味です。「関数の二重定義」の意味は後で説明するとして、WordPressでこのエラーが起きる原因の多くがfunctions.phpの修正ミスです。

たとえば、親テーマのfunctions.phpからすべてのコードをコピーして子テーマのfunctions.phpにペーストしていませんか?

functions.phpの内容をコピーペーストするとエラーになる
functions.phpの内容をコピーペーストすると「Fatal error: Cannot redeclare」になる

一般的な子テーマを使ったカスタマイズ方法として「使いたいファイルを子テーマにコピーする」と聞いたかもしれませんがfunctions.phpは別です。単純に親テーマのfunctions.phpの内容をコピーして子テーマのfunctions.phpにペーストすると、「Fatal error: Cannot redeclare …」になります。

この場合、対処法は簡単で、子テーマのfunctions.phpにコピーペーストした部分を削除すれば大丈夫です。

なぜ「Fatal error: Cannot redeclare …」になるのか

なぜ「Fatal error: Cannot redeclare …」になるのか、仕組みを説明します。

同じ機能は作成できない

functions.phpの内容を子テーマにコピーペーストするとエラーになる理由は、同じ名前の機能を作成できないからです。functions.phpはサイトで使う機能の集合です。カスタム投稿タイプ、ヘッダー画像、サイドバー、各種ショートコードなど、膨大な機能が定義されています。

これらの膨大な機能は呼び出しやすいように「function」という単位でまとまっているのが一般的です。たとえば、「こんにちは!」と表示するショートコード[hello]を作るため次のような「function」が作成されているかもしれません。

/* あいさつを表示 */
function disp_hello() {
    return "こんにちは!";
}
add_shortcode('hello', 'disp_hello');

同じ名前のfunction(関数)は作成できないため、次のように同じfunctionを2つ作成するとエラーになります。

/* あいさつを表示 */
function disp_hello() {
    return "こんにちは!";
}
add_shortcode('hello', 'disp_hello');

/* あいさつを表示 */
function disp_hello() {
    return "おはよう!";
}
add_shortcode('hello', 'disp_hello');

親テーマから子テーマにfunctionをコピーペーストするとエラーに

上記と同じ仕組みですが、親テーマのfunctions.phpから個々のfunctionを抜粋してコピーペーストしてもエラーになります。同じfunctionができてしまうからです。

親テーマのfunctionを子テーマにコピーペーストすると「Fatal error: Cannot redeclare」に
親テーマのfunctionを子テーマにコピーペーストすると「Fatal error: Cannot redeclare」に

対処法としては、安易に親テーマのfunctionを子テーマにコピーペーストしないことです。

functionをコピーしても良い場合

どうしても子テーマでカスタマイズしたい場合もあるでしょうから、親テーマから子テーマにfunctionをコピーペーストしても問題ないケースを紹介します。

「関数が存在しないときのみ」の条件が付いている場合

親切なテーマの場合、親テーマのfunctionが子テーマにコピーペーストされることを想定したコードになっている場合があります。具体的にはifとfunction_existsという命令を使って「関数が存在しない場合のみ、次の関数を定義してください」と書いてある場合があります。

たとえば、次のようなコードです。

if (!function_exists( 'disp_hello' ) ) {
    /* あいさつを表示(こんにちは) */
    function disp_hello() {
        return "こんにちは!";
    }
    add_shortcode('hello', 'disp_hello');
}

このように「関数が存在しなければ」のif文で囲んである関数は親テーマから子テーマのfunctions.phpにコピーペーストしても問題ありません。関数の存在チェックをしているので同じfunctionが重複せず、「Fatal error: Cannot redeclare」になりません。

このようなテーマではfunctionを子テーマのfunctions.phpにコピーペーストしてカスタマイズすれば、そちらが親テーマより優先されるので自由にカスタマイズできるようになります。

/* あいさつを表示 */
function disp_hello() {
    return "おはよう!";
}
add_shortcode('hello', 'disp_hello');

後から読み込まれる親テーマでは同じfunctionが作成されないので子テーマのカスタマイズ内容が反映されます。

子テーマのカスタマイズ内容が反映される
子テーマのカスタマイズ内容が反映される

一時的に親テーマを編集する場合

同名関数の存在チェックがないテーマで、どうしても子テーマでfunctionをカスタマイズしたい場合は、一時しのぎですが親テーマのfunctionを「関数が存在しなければ」のif文で囲んでみる方法があります。

たとえば、親テーマに次のようなfunctionがあります。

/* あいさつを表示 */
function disp_hello() {
    return "こんにちは!";
}
add_shortcode('hello', 'disp_hello');

これを「関数が存在しなければ」というif文で囲みます。

if (!function_exists( 'disp_hello' ) ) {
    /* あいさつを表示 */
    function disp_hello() {
        return "こんにちは!";
    }
    add_shortcode('hello', 'disp_hello');
}
「disp_hello」の部分は実際の関数名に直す必要があります。

これで親テーマのfunction(この例ではdisp_hello関数)を子テーマのfunctions.phpにコピーペーストして自由に編集できるようになります。

ただし、親テーマをアップデートするとfunctions.phpが上書きされて元に戻り「Fatal error: Cannot redeclare …」が発生する可能性があるのでアップデート前に対処が必要です。あくまで、「親テーマをカスタマイズするとアップデート時に全部消えてしまうので子テーマでカスタマイズしたい」の一時しのぎです。

まとめ

以上、WordPressで「Fatal error: Cannot redeclare …」が発生する典型的な例と対処法を紹介しました。原因は安易なコピーペーストがほとんどです。functionが重複できないという仕組みを理解して、エラーに対応できるようにしましょう。

WordPressトラブル