suin.io

register_globalの代替策としてextract

suin2009年2月8日

かならず、周期的に出てくる話題のひとつがregister_globalとextractの話。韓国でも今ホットな話題のようで、「register_global = offの代替策でextract($_GET)とかやったら、ひどい目に遭いました」という報告があがっています。スレッドを見てみると、こんなレスも...。

extract($_GET)は下手すると、$_SERVER['REMOTE_ADDR ']が上書きされちまうらしいぜ。
なんでも、$_GET['REMOTE_ADDR ']があると、改ざんの危険があるっぽい。

$_GET['REMOTE_ADDR '] がセットされた$_GETをextractしても$_SERVER['REMOTE_ADDR ']は上書きされず、$REMOTO_ADDRという変数ができるだけだと思うんだけどな~。

$_SERVERが上書きされるケースは、$_GET['_SERVER']があるとき。

だからextractは怖いんですよね。

XOOPSでもかつて盛り上がった話題でしたが、コアのあちこちでextract($_GET)をしていて、いったんextractが危ないと認知されるとextractは使わなくなったものの、 今度はforeach($_GET as $key => $value ) $key = $value;とかするようになったりしたことがありました。結局、extractをやめてもforeachで「展開」すればextractをしていることと同じです。楽な方法があると、やっぱり楽な方法でやってしまうのが人の常なのでしょうか。

でも、extract自体は決して危険な関数ではないと考えます。使い方さえしっかりしていれば、とても便利な関数です。私が使うときに漠然とですが注意しているのは、次の点でしょうか。

  • グローバールスコープの配列はextractしない。
  • extractがグローバルスコープの変数を生み出すときも使わない。
  • 配列の中身がある程度固定されているときに使う。
  • できるだけ他の変数に影響の出ない使い方をする。
    • extractは変数があれば上書きしないとか、接頭辞をつけるとかのオプションがあるので、それを利用する。
    • 処理の最初のうちにextractをやっておき、extractが上書きすることは避ける。

それでも、最近はやっぱりextractはあまり使わないようになってきています。それは、extractが危険だからとかいう考えではなく、extractを使うと、できあがったコードが読みにくいものになるという、書き方上の問題が出てきたからです。

extractたった一行で、いくつもの変数を一度に定義できてしまうので、その変数がどこからやってきたのかがたちまちに不明瞭になってしまいます。そのため、最近では、配列の要素が固定されているときは、ちくいち書くようにしています。コードの分量が増えても、そちらのほうがわかりやすいからです。

PHP6で、やっとregister_globalが廃止になるんで喜んでますが、register_global = On が前提のプログラムは対策し直しましょうみたいな雰囲気になって、知らずにextractがばんばん発動するんじゃないかと心配するところもあります。

RELATED POSTS