綾小路龍之介の素人思考

序論:cgiがクエリをもらう時の良くある方法にスマートなものが無い理由

探しても探しても出てくるのは下のようなものかこれの亜種ばかり。これが一番なのか?1ブロックに1機能もいいけど1行で1機能を追及したいな。大体共有サーバで容量制限がある中では1文字でも惜しいしね。とりあえず今のところは可読性のある論理1行でクエリを変数に取り込むという機能がほしいな。

if($ENV{'REQUEST_METHOD'} eq 'POST'){
  read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
}else{
  $buffer = $ENV{'QUERY_STRING'};
}

if}else{}を3項演算子で1行に集約できないかな?と言うことで下のようになる。でもこれだけだと余り嬉しくないな。だって2度と使わないスカラー変数$bufferを使っているからね。だから願わくば$buffer=として受け取りたい。だって、この後にハッシュにキーと値を入れる時にsplit文で切り分けるけど、この時に切り分け対象文字列の含まれた変数を指定しなきゃならないからね。でも良く考えてみればこの問題はすぐに解決するかもしれない。split文は何も指定なければ特殊変数$_を切り分け対象文字列の含まれた変数として取るんだ。このことを使えないかな。

$ENV{'REQUEST_METHOD'} eq 'POST' ? read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}) : ( $buffer = $ENV{'QUERY_STRING'} );

そう、$bufferを$_に置き換えてしまえば良いんだ。例えば下のような感じにできる。このほうが1行が短くできるし、自分で定義した変数を使っていないと言う点でアドバンテージがあると思うなぁ。何よりブロックで囲んで$bufferにmy宣言をしなくてもいいと言うのが楽だ。

$ENV{'REQUEST_METHOD'} eq 'POST' ? read(STDIN,$_,$ENV{'CONTENT_LENGTH'}) : ( $_ = $ENV{'QUERY_STRING'} );

さて、良くある例に戻って考える。いまスカラー変数$bufferにクエリの内容が入っている。これを分割してハッシュに格納したい。良くある例は下のような感じかな。まぁ突っ込みどころ満載のスクリプトだけどさ。やっぱり見やすいけど長い。連想配列に格納するだけにしては勝手に定義した変数を4つも使っているのはなんだかいやだな。

my @query = split/&/,$buffer;
foreach(@query){
        my ($key,$value) = split/=/,$_;
        $key     = &UreDecode($key);
        $value   = &UreDecode($value);
        $q{$key} = $value;
}

文句言ってても始まらないので短くしてみる。下のような感じだ。上のやつとは異なる結果を返すが、実用上ほとんど相違ないと判断したのがこれ。ただ正規表現による篩い分けを行っているので特にクリエが長くなった時の実行速度に難ありかも。でも篩い分けは必要だWebMasterは悪意ある入力からSystemを守らなければならないと思うから。

my %q = map{&UrlDecode($_)}map{m/^([^=]+)=([^=]+)$/}split/&/;

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2008-01-28T13:25:22+09:00
  2. Modified: 2008-01-28T05:28:43+09:00
  3. Generated: 2017-06-25T23:09:17+09:00