[PHP] 非推奨になったcreate_functionを無名関数で書き換え

By | 2017年8月25日

PHPには、無名関数クロージャ)を作成する関数である create_function があります。

create_function(引数, コード本体)

これは、引数とする変数や関数内のコードを文字列(String)として書くことで無名関数を作成できる関数です。

しかし、この関数はPHPのバージョン「7.2.0」以降では非推奨となりました。理由は、セキュリティおよび動作効率上の問題があるからです。PHPには標準の機能によって無名関数を定義できるため、そちらを使うことが推奨されています。

警告
この関数は PHP 7.2.0 で 非推奨になります。この関数に頼らないことを強く推奨します。
...
警告
この関数は、内部的に eval() を実行しているので、 eval() と同様にセキュリティ上のリスクがあります。 さらに、パフォーマンスやメモリ使用効率の面でも問題があります。
PHP 5.3.0 以降を使っている場合は、この関数ではなく、ネイティブの 無名関数 を使うべきです。
PHP: create_function - Manual

今回は、実際に create_function によって無名関数を作る処理を、ネイティブによる無名関数の定義に書き換える例について紹介します。

書き換えるサンプルのスクリプト

例えば、以下のような create_function による無名関数を使用したスクリプトがあるとします。

<?php

	$text = "このテキストが含む12数字だけを87大きくする038";
	$fontSize = 24;
	
	// preg_replace_callback で使う無名関数を作成
	$callback = create_function(
		'$matches',
		'return \'<strong style="font-size: ' . $fontSize . 'px;">\' . $matches[0] . \'</strong>\';'
	);

	// 無名関数で定義した正規表現による置換の結果を出力
	echo preg_replace_callback('/(\d+)/', $callback, $text);
?>

このスクリプトは、ある文字列に含まれる数字だけを、大きなフォントのスタイルを適用したstrongタグで囲まれた状態に置換するものです。

関数 preg_replace_callback は、無名関数を使って正規表現にマッチした文字列を置換します。

これを実行してブラウザに結果を出力すると、以下のようになります。

preg_replace_callback によって無名関数で文字列の一部を置換した例

このスクリプトにおける create_function をネイティブの無名関数に書き換えてみます。

まず、見た目通りに書き換えてみると、スクリプトは以下のようになります。

<?php

	$text = "このテキストが含む12数字だけを87大きくする038";
	$fontSize = 24;
	
	// preg_replace_callback で使う無名関数を作成
	$callback = function($matches) {
		return '<strong style="font-size: ' . $fontSize . 'px;">' . $matches[0] . '</strong>';
	};

	// 無名関数で定義した正規表現による置換の結果を出力
	echo preg_replace_callback('/(\d+)/', $callback, $text);
?>

しかし、これを実行すると以下のようなエラーが出ます。

無名関数内から関数外に定義された変数にアクセスしようとしたときのエラー

これは、create_function を使った場合と異なり、ネイティブの無名関数内からでは関数外に定義されている変数 $fontSize にアクセスできないためです。

そして、今回のスクリプトでは、無名関数は preg_replace_callback で使用されるため、引数を以下のように2つ設定するわけにはいきません。

...

$callback = function($matches, $fontSize) {
	return '<strong style="font-size: ' . $fontSize . 'px;">' . $matches[0] . '</strong>';
};

...

このような場合は、変数を親のスコープから引き継ぐための use を関数定義時に使用します。具体的には、以下のように無名関数を定義することで、無名関数内から関数外にある変数にアクセスできます。

<?php

	$text = "このテキストが含む12数字だけを87大きくする038";
	$fontSize = 24;
	
	// preg_replace_callback で使う無名関数を作成
	$callback = function($matches) use ($fontSize){
		return '<strong style="font-size: ' . $fontSize . 'px;">' . $matches[0] . '</strong>';
	};

	// 無名関数で定義した正規表現による置換の結果を出力
	echo preg_replace_callback('/(\d+)/', $callback, $text);
?>

以上、create_functionをPHP標準の無名関数に書き換える方法でした。

今回の記事で登場した関数についての詳しい説明は以下のドキュメントを御覧ください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*