PHPの"eval"関数で文字列を判定する時の書き方サンプル

2018年8月24日

PHP テクノロジー プログラミング

セキュリティ的にあまり使わない方がいいとされているeval関数ですが、PHPでもjavascriptでも今だに存続しているのは、eval関数でしかできない事があるからでしょう。 どういう時に使うのかというと、最近触れているWEBブラウザでプログラムが書けるcodepenのようなサイトが増えてますが、入力されたテキストをプログラム処理として実行させる時にeval関数は非常に便利に使う事ができます。 もちろん便利の反面、サーバーサードでの実行処理を無作為に解放してしまうと、思いもよらない処理を実行されてサーバーを壊されたり乗っ取られたり、悪意の踏み台にされたりするので、そうした知識も合わせて備えておかなければいけません。 今回はとある処理でPHPのeval関数を使う事になり、普段あまり使わないので、調べた内容や仕様ポイントなどをまとめておきました。

今回の作業内容

とあるWEBサービスの構築をする際に、PHPで任意のコードを表示する際にif文として判定しなくてはいけなくて、その記述がif文の判定内容のような記述をするようになっており、どうしても、文字列をif文処理しなければいけなかったので、eval関数を使わないといけませんでした。 判定内容がルール化されていれば、match処理程度で出来るんですが、フレームワークレベルって柔軟に作らないといけないために、evalを使わざるを得ないのですね。 そして、以下のような処理を書いて見たところ、思いの外はまってしまったポイントがあったので、備忘録! <?php $str = " 'ABC' === 'ABC' "; if(eval($str)){ echo "true"; } else{ echo "false"; } まず上記の様に書いて見たら"Error !!!!!" if文内に記述するevalなんで、if文の判定部分だけあればいいのかと勘違いしていました。 正しくは下記の様に書かないといけなかった様です。 <?php $str = " 'ABC' === 'ABC' "; $if = "if(".$str."){return true;}else{return false;}"; if(eval($if)){ echo "true"; } else{ echo "false"; } 上記の様に"if"文を"eval"内にちゃんと記述して"return"またはechoしてあげないと、値を受け取れません。 eval関数は、無名関数のようなものだと考えると理解しやすかったです。

三項演算をreturnすると便利

上記の様にif文の中にif文を書くのがどうしても気持ち悪いと考えてしまう僕としては、内部を三項演算にする事でスッキリ記述する事ができました。 <?php $str = " 'ABC' === 'ABC' "; $if = "return (".$str.") ? true : false;"; if(eval($if)){ echo "true"; } else{ echo "false"; } どうでしょうか? 非常にすっきりした判定文になっていると思いませんか? 短い文字列で動作するのですっきり具合が気持ちいいレベルです。 ただし注意点としては、文末の";"セミコロンを記述するのを忘れない様にしないと、PHPではエラーになります。 ※javascriptで使う場合は、1文のみのプログラムであれば、";"セミコロンは割愛できます。 eval内部は、単体のプログラムである事を理解していれば、この必要性は理解できると思います。

三項演算子の数珠つなぎパターン

上記プログラムだと、1パターンの○×判定しかできないのですが、参考演算しを数珠つなぎする事で、elseif対応する事が可能になります。 <?php $val = "GHI"; $if = "return ( 'ABC' == '".$val."' ) ? 1 : (( 'DEF' == '".$val."' ) ? 2 : (( 'GHI' == '".$val."' ) ? 3 : 4)); "; echo eval($if); ここで気をつけるポイントは、三項演算子を複数つなぎ合わせる時に、それぞれの結果部分が干渉してしまうので、"()"でくくってあげなければいけません。 若干見た目が気持ち悪くなってしまうんですが、もしかしたらswitchの方がいいかもしれませんね。 $val = "DEF"; $switch = "switch('".$val."') {case 'ABC': echo 1;break; case 'DEF': echo 2;break; case 'GHI': echo 3;break; default: echo 4;break;}"; echo eval($switch); 1行でswitch文を書くと非常に分かりづらいですね・・・ とにかく使い慣れると非常に便利なeval関数です、内部で実行する文字列に注意して、効率的に使って見てはいかがでしょうか?

参考ページ

リファレンスページ PHPマニュアル : eval 過去記事「[JavaScript] evalの返り値についての研究」 [JavaScript] evalの返り値についての研究

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。