PHP 7.2+アップグレード後の「Deprecated: Function create_function() is deprecated」を修正する方法

intermediate🐘 PHP2026-03-23| PHP 7.2+、PHP 8.x — Linux/Ubuntu/CentOS、任意のWebサーバー(Apache、Nginx + PHP-FPM)

Error Message

Deprecated: Function create_function() is deprecated
#php#deprecated#アップグレード#互換性

エラーの内容

PHPをアップグレードした(あるいはホスティング側が勝手にアップグレードした)後、ログが以下のメッセージで埋め尽くされています:

Deprecated: Function create_function() is deprecated in /var/www/html/wp-includes/functions.php on line 4587
Deprecated: Function create_function() is deprecated in /var/www/html/app/lib/template.php on line 112

PHP 8.0ではこれが致命的なエラーに昇格し、ページが真っ白になります。深夜2時に、これほど困るものはありません。

なぜこのエラーが発生するのか

create_function()は2000年にPHP 4.0.1で導入された関数です。PHP 7.2で非推奨となり、PHP 8.0で完全に削除されました。内部的にはeval()のラッパーに過ぎず、実行時に文字列から無名関数をコンパイルします。これはセキュリティ上の脆弱性であり、パフォーマンスの低下にもつながります。PHP 5.3で導入された本来のクロージャは、こうした問題を一切抱えずに同じ処理を実現できます。

アップグレード後にこのエラーが表示される場合、自分のコードまたはサードパーティのライブラリがまだこの古いパターンを使用しています。

ステップ1 — すべての該当箇所を洗い出す

範囲を推測するのではなく、実際に調査しましょう。プロジェクトのルートから以下を実行します:

grep -rn "create_function" /var/www/html --include="*.php"

vendor/node_modules/を除外する場合:

grep -rn "create_function" /var/www/html \
  --include="*.php" \
  --exclude-dir=vendor \
  --exclude-dir=node_modules

ファイルと行番号をすべてメモしておきましょう。自分のコードに10箇所あれば、午前中の作業で対応できます。すべてがvendor/内であれば、ステップ3へ直接進んでください。

ステップ2 — create_function() をクロージャに書き換える

パターンは常に同じです。引数の文字列とコードの文字列があれば、それを本来の無名関数に置き換えます。

// 旧 — PHP 4スタイル、7.2で非推奨、8.0で削除
$greet = create_function('$name', 'return "Hello, " . $name . "!";');
echo $greet('World'); // Hello, World!
// 新 — PHP 5.3〜8.x で動作
$greet = function($name) {
    return 'Hello, ' . $name . '!';
};
echo $greet('World'); // Hello, World!

array_mapusortなどに渡すコールバックが最もよく見られるケースです:

// 旧
$doubled = array_map(create_function('$x', 'return $x * 2;'), [1, 2, 3]);

// 新 — 無名関数
$doubled = array_map(function($x) { return $x * 2; }, [1, 2, 3]);

// アロー関数を使えばさらにすっきり(PHP 7.4+)
$doubled = array_map(fn($x) => $x * 2, [1, 2, 3]);

古いコードが外部変数を文字列本体に展開している場合は、use句に変換します:

// 旧 — 文字列展開によるハック
$multiplier = 5;
$fn = create_function('$x', "return \$x * {$multiplier};");

// 新 — 明示的な変数キャプチャ
$multiplier = 5;
$fn = function($x) use ($multiplier) {
    return $x * $multiplier;
};

ステップ3 — vendor/ 内のサードパーティコードへの対処

vendor/配下のファイルを直接編集してはいけません。次回のcomposer updateで変更が上書きされ、振り出しに戻ってしまいます。

問題のあるパッケージに新しいバージョンが存在するか確認します:

composer outdated

該当パッケージだけを更新します:

composer update vendor/package-name

更新版がなく、今すぐPHP 8.0が必要な場合は、以下の2つの選択肢があります:

  • パッケージをフォークして自分で修正を適用し、repositoriesエントリ経由でcomposer.jsonがフォーク先を参照するようにする。
  • 積極的にメンテナンスされている代替パッケージに置き換える。

WordPressサイトの場合、古いプラグインがこれらの警告の大部分の原因です。一括更新しましょう:

wp plugin update --all

ステップ4 — 非推奨通知を一時的に抑制する(暫定対応のみ)

今夜ホットフィックスをリリースしなければならず、本格的なリファクタリングは後回しにしたい場合は、アプリケーションレベルで非推奨通知を抑制できます。ただし注意が必要です。これはPHP 7.xで警告を消すだけです。PHP 8.0では関数自体が削除されているため、引き続きクラッシュします。

// bootstrap/index.php — TODOとしてマークして後で対応すること
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);

設定ファイルで指定する場合:

# php.ini
error_reporting = E_ALL & ~E_DEPRECATED

# .htaccess (Apache)
php_value error_reporting "E_ALL & ~E_DEPRECATED"

これで稼げるのは数時間です。数週間ではありません。

修正の確認

対象ページをリロードしながらPHPエラーログを監視します:

# PHPエラーログをリアルタイム確認
tail -f /var/log/php/error.log
# または
tail -f /var/log/nginx/error.log

コマンドラインで特定のファイルを構文チェックします:

php -l path/to/fixed-file.php
# 出力例: No syntax errors detected in path/to/fixed-file.php

アプリケーションディレクトリ全体を再帰的に構文チェックし、問題のないファイルを除外します:

find /var/www/html/app -name "*.php" -exec php -l {} \; 2>&1 | grep -v "No syntax errors"

何も出力されなければ、問題ありません。

本番環境に持ち込む前に検出する

create_function()の呼び出しが1つでもPHP 8.0のサーバーに紛れ込めば、ページが真っ白になります。RectorをCIパイプラインに組み込んで、このクラスのバグをコミット時点で防ぎましょう:

# Rectorのインストール
composer require rector/rector --dev

# ドライラン:変更内容を事前確認
vendor/bin/rector process src --dry-run

Rectorはcreate_function()からクロージャへの変換を理解しており、多数の該当箇所を自動的に書き換えることができます。一度実行してdiffを確認し、コミットすれば完了です。

クイックリファレンス

  • PHP 7.2create_function() 非推奨(E_DEPRECATED警告)
  • PHP 8.0create_function() 削除(致命的エラー、ページ真っ白)
  • 修正方法:無名関数function() {}またはアロー関数fn() =>として書き直す
  • サードパーティコード:Composerでパッケージを更新する — vendor/を直接編集しない
  • CIガード:RectorまたはPHPStanを追加して非推奨な呼び出しをデプロイ前に検出する

Related Error Notes