セキュリティ的にあまり使わない方がいいとされている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の返り値についての研究
0 件のコメント:
コメントを投稿