preg_replace_callback のコールバック関数に複数引数を指定したい 
2016/05/31 Tue.
PHPに「preg_replace_callback」という関数があります。
使い方は
preg_replace_callback(正規表現パターン, コールバック関数, 置換元文字列);
です。
正規表現に「([0-9]+)」みたいなグループ指定があり、その値を利用して作成された文字列で置換を行いたいときにとても便利です。
単純に正規表現マッチだけをコールバック関数で利用する場合は簡単で、
preg_replace_callback('/([0-9]{3})-([0-9]{4})/', function ($matches) { return sprintf('%03d%04d', $matches[1], $matches[2]); }, $strings);
こんな感じで使えます。
しかし、今回コールバック関数に複数引数を指定する方法で困っていろいろ試してみたので備忘録メモ。
使い方は
preg_replace_callback(正規表現パターン, コールバック関数, 置換元文字列);
です。
正規表現に「([0-9]+)」みたいなグループ指定があり、その値を利用して作成された文字列で置換を行いたいときにとても便利です。
単純に正規表現マッチだけをコールバック関数で利用する場合は簡単で、
preg_replace_callback('/([0-9]{3})-([0-9]{4})/', function ($matches) { return sprintf('%03d%04d', $matches[1], $matches[2]); }, $strings);
こんな感じで使えます。
しかし、今回コールバック関数に複数引数を指定する方法で困っていろいろ試してみたので備忘録メモ。
まず、コールバック関数に複数引数は指定できません。
別途関数を定義し、
kansu($matches, $data)
とやってもうまく動きません。
また、無名関数に
function ($matches, $data) { }
と指定しても動きません。
強引に無名関数の中に変数をねじ込んでも
function ($matches) { return $matches[1] . $data; }
当然だめです。無名関数の中と外で変数のスコープが切れてるからね。
ということで、コールバック関数に複数引数を渡す方法を考えてみました。
まず、簡単、強引な方法。
■グローバル変数
要はスコープがつながっていればなんとでもなる。
ということで、コールバック関数の中で使う正規表現マッチ以外の変数をグローバル変数にセットする。
そして、関数内で「$GLOBALS['']」で呼び出す。
「困ったときにすぐグローバル変数使う奴、嫌いやわ~」というもっともなご意見の方向き。
■FUNCTION USE
まあ、普通これですよね。
使い方は
function ($matches) use ($data) { return $matches[1] . $data; }
ね?簡単でしょ?
注意としては配列の場合。上の例で「$data」が配列の場合、配列全体を渡すことはできますが、配列の一部「$data[0]」みたいな指定の仕方をするとエラーになります。
物事を難しく考えたい。あえてね。そんな方に。
■CREATE_FUNCTION
コールバック関数内で使う変数を先に展開して「リテラル値」として使います。
create_function('$matches', "return \$matches[1] . '{$data}';")
これには注意点がいろいろあります。
変数を展開するため「create_function」の第二引数を「ダブルクォーテーション」で囲っています。そのため、関数内で「変数」として使いたい変数には、「$」の前に「エスケープ文字(\)」を付けてあげないといけません。
次に、展開して使う変数は、この関数が実行される時点でリテラル定義となっています。変数の内容が文字列の場合は「文字囲い(シングルクォーテーションかダブルクォーテーション)」が必要です。
たとえば、
strlen($data);
と普段やりますが、
strlen('$data');
とやらないとエラーになる場合があります。
さらに、展開する変数がシングルクォーテーションを持っている場合、
$data = "'文字列1','文字列2'";
のような場合、そのまま展開させると以下のようにおかしくなります。
strlen(''文字列1','文字列2'');
そこで、事前にエスケープ処理やエンコード処理など何らかの対策が必要となります。めんどうです。コードが増えると頭が混乱します。
それでは、それぞれの使い方例。
■グローバル変数
$GLOBALS['DATA'] = $data;
preg_replace_callback('/([0-9]+)/', function ($matches) { return sprintf('%s%d', $GLOBALS['DATA'], $matches[1]); }, $strings);
■FUNCTION USE
preg_replace_callback('/([0-9]+)/', function ($matches) use ($data) { return sprintf('%s%d', $data, $matches[1]); }, $strings);
■CREATE_FUNCTION
preg_replace_callback('/([0-9]+)/', create_function('$matches', "return sprintf('%s%d', '{$data}', \$matches[1]);"), $strings);
デース
別途関数を定義し、
kansu($matches, $data)
とやってもうまく動きません。
また、無名関数に
function ($matches, $data) { }
と指定しても動きません。
強引に無名関数の中に変数をねじ込んでも
function ($matches) { return $matches[1] . $data; }
当然だめです。無名関数の中と外で変数のスコープが切れてるからね。
ということで、コールバック関数に複数引数を渡す方法を考えてみました。
まず、簡単、強引な方法。
■グローバル変数
要はスコープがつながっていればなんとでもなる。
ということで、コールバック関数の中で使う正規表現マッチ以外の変数をグローバル変数にセットする。
そして、関数内で「$GLOBALS['']」で呼び出す。
「困ったときにすぐグローバル変数使う奴、嫌いやわ~」というもっともなご意見の方向き。
■FUNCTION USE
まあ、普通これですよね。
使い方は
function ($matches) use ($data) { return $matches[1] . $data; }
ね?簡単でしょ?
注意としては配列の場合。上の例で「$data」が配列の場合、配列全体を渡すことはできますが、配列の一部「$data[0]」みたいな指定の仕方をするとエラーになります。
物事を難しく考えたい。あえてね。そんな方に。
■CREATE_FUNCTION
コールバック関数内で使う変数を先に展開して「リテラル値」として使います。
create_function('$matches', "return \$matches[1] . '{$data}';")
これには注意点がいろいろあります。
変数を展開するため「create_function」の第二引数を「ダブルクォーテーション」で囲っています。そのため、関数内で「変数」として使いたい変数には、「$」の前に「エスケープ文字(\)」を付けてあげないといけません。
次に、展開して使う変数は、この関数が実行される時点でリテラル定義となっています。変数の内容が文字列の場合は「文字囲い(シングルクォーテーションかダブルクォーテーション)」が必要です。
たとえば、
strlen($data);
と普段やりますが、
strlen('$data');
とやらないとエラーになる場合があります。
さらに、展開する変数がシングルクォーテーションを持っている場合、
$data = "'文字列1','文字列2'";
のような場合、そのまま展開させると以下のようにおかしくなります。
strlen(''文字列1','文字列2'');
そこで、事前にエスケープ処理やエンコード処理など何らかの対策が必要となります。めんどうです。コードが増えると頭が混乱します。
それでは、それぞれの使い方例。
■グローバル変数
$GLOBALS['DATA'] = $data;
preg_replace_callback('/([0-9]+)/', function ($matches) { return sprintf('%s%d', $GLOBALS['DATA'], $matches[1]); }, $strings);
■FUNCTION USE
preg_replace_callback('/([0-9]+)/', function ($matches) use ($data) { return sprintf('%s%d', $data, $matches[1]); }, $strings);
■CREATE_FUNCTION
preg_replace_callback('/([0-9]+)/', create_function('$matches', "return sprintf('%s%d', '{$data}', \$matches[1]);"), $strings);
デース
- 関連記事
category: PHP
この記事へのコメント
コメントの投稿
コメントは全て管理人が内容を確認してから表示されます(非公開コメント除く)。
内容によっては表示されない場合がありますことご了承願います。
内容によっては表示されない場合がありますことご了承願います。