Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

GETとPOSTどちらでもOKなデータ受信関数の研究

研究内容

HTMLフォームからのデータの送信方法にはGET/POSTの2通りがありました。 どちらでデータを送るのかはHTML側で指定しますが、 CGIプログラム側で、どちらの形式でもデータを受け取れるようにしておけば、 便利ですよね。HTML側で、どちらの形式でデータを送ったらいいんだろう? と考えずに済みますから。もしそうなっていなくて、 GETしか受け取れないCGIプログラムには必ずGETで、 POSTしか受け取れないCGIプログラムには必ずPOSTで、なんてことに なったらそらもう大変ですよね。

GET/POSTのどちらでもデータを受け取れる仕組み。便利です。 こういう便利なものっていうのは、関数っていうものにしておくと 分かりやすくてもっと便利です。 GET、POST、どちらの送信方法にも対応した、フォームデータ取得関数 getformdata関数を作成します。

結果

GET/POSTの判別

CGIプログラム側でGET/POSTの両方に対応するためには、 どちらの形式でデータが送られてきたのか知る必要があります。 どうやったらそれが分かるか。そう、環境変数 REQUEST_METHOD に入っている文字列が GET か POST かで区別ができるのでした。 環境変数 REQUEST_METHOD の値によって自動的に処理を変えればいいんですね。

条件文 if

GETならこっちの処理、POSTならこっちの処理、ということをPerlで行うには if 文というものを 使います。if というのは英語で「もし(…だったら)」という意味ですね。 if 文というのはまさにその意味のとおり「もし〜だったら〜する」ということを実現するものです。 これを使えば、もしGETなら〜もしPOSTなら〜、ということができるわけです。

文字列比較

もしGETだったら、というのはどうやって表現するのでしょうか。 それには、比較ということをします。 データ送信方法は $ENV{'REQUEST_METHOD'} に入っているんでした。 これが GET だったら…というのは、if 文と、演算子 eq を使って次のように書きます。

if ($ENV{'REQUEST_METHOD'} eq "GET") {
	# GET用の処理
}

eq というのは同じかどうかを調べる演算子で、上のコードは 「もし $ENV{'REQUEST_METHOD'} が GET に等しければ、〜する」という意味になります。 「等しければ」なんて書くと耳慣れないのでヘンな感じですが、要するに 「GETなら〜する」という意味です。 if 文って結構、普通の言葉に近くて分かりやすいですよね。

そうでなければ〜

ここまでで、GETとPOSTで処理を分けるには次のようにしたら良いことが分かりました。

if ($ENV{'REQUEST_METHOD'} eq "GET") {
	# GET用の処理
}
if ($ENV{'REQUEST_METHOD'} eq "POST") {
	# POST用の処理
}

「GETなら〜する、POSTなら〜する」です。 これでもいいですが、「そうでなければ〜」というものを使うとちょっと短くなります。 送信方法はGETとPOSTしかありませんので、GETでなければPOSTに決まっています。 こういう場合は、次のように else を使って書くこともできます。

if ($ENV{'REQUEST_METHOD'} eq "GET") {
	# GET用の処理
}
else {
	# POST用の処理
}

「if 〜 else 〜」は「もし〜ならば〜、そうでないならば〜」という意味です。 ここでは「GETなら〜する、そうでないなら〜する」ということですね。

作ってみましょう

GETかPOSTかで処理を分ける方法は分かりました。 それでは、実際に作ってみましょう。 データの取得方法は研究済みです。次のようになりますね。

if ($ENV{'REQUEST_METHOD'} eq "GET") {
	$formdata = $ENV{'QUERY_STRING'};
}
else {
	read(STDIN, $formdata, $ENV{'CONTENT_LENGTH'});
}

このコード(プログラム)は、GET、POSTのどちらでも、送られてきたデータを 変数 $formdata に入れるものです。

関数にします

さて、今回の研究のもう1つの目的は関数というものを作ることです。 関数は、サブルーチンともいいます。 関数というのは、今までにreadというものが出てきました。 なにか1つの決まったことをしてくれる便利なもの。それが関数です。 Perlでは、subというキーワードを使って、関数を作ります。 次のような形式になります。

sub 関数名
{
}

関数名っていうのはなんでも構いません。自分で好きなように付けることができます。 ただし、まだ使われていない新しいものにしないと駄目です。混ざっちゃ困りますからね。

さて、関数っていうのは戻り値っていうものを指定することができます。 数学でも、関数っていえば、なにか値を表すものでしたよね? (f(x)=〜 とか。懐かしいですね。) プログラムでも同じで、関数っていうのはなにかデータを返すことができるんです。 数学の関数と違って、返すデータは数値だけじゃなくて文字列とかでもOKです。 関数の最後の return 文というもので指定します。

さあ、関数の作成です。まず関数名を決めましょう。 関数名に日本語は使えませんから、僅かしかない英語の知識を使ってなんとか英語の関数名を考えます。 (ローマ字でもいいんですけど、英語の方がかっこいいですもんね。) 今回作りたいのは、フォーム(form)から送られてきたデータ(data)を取得する(get)関数なので、 getformdataという名前の関数にしましょう! 管理人は(動詞)+(名詞)というのが分かりやすいと 思いましたので、こういう関数名にしました。 取得したいのは送られてきたデータですから、それをreturn文で返すようにします。 こんな感じです。

sub getformdata
{
	local $formdata;
	if ($ENV{'REQUEST_METHOD'} eq "GET") {
		$formdata = $ENV{'QUERY_STRING'};
	}
	else {
		read(STDIN, $formdata, $ENV{'CONTENT_LENGTH'});
	}
	return $formdata;
}

また新しく、localっていうキーワードが出てきましたね。 「local 変数名」とすると、「この変数はこの関数の中だけで使いますよ、 もし他に同じ名前の変数があっても、この関数の中のものとはまったく別物ですよ」 ということを指示することができます。なんでこれが必要かっていうと、 関数名は他のものと重ならないようにしなきゃいけないっていうことがありましたが、 同様に、変数名も、他の変数と重ならないようにしないと、混ざっちゃうのです。 この関数では $formdata っていう変数を使っていますが、 関数の外に、もし $formdata っていう変数が既にあったら、 データが混ざって大変なことになってしまいます。 でも関数って、関数の外のことは何も知らないっていう気持ちで作らなきゃいけないんです。 関数の外で $formdata っていう変数が使われているかどうかなんて分からない、 でももし使われていたら大変なことになる…っていう困った事態を避けるために、localという キーワードを使います。localってしておけば、同じ変数が関数の外にあっても 問題無いんです!関数の中で使う変数は、常にlocalの指定をしておくっていうのが とても大事です。だから、もう、とにかくlocalにしておきましょう。

さてここで、local のとても重要な注意点があります。 複数の変数を local にするときですが、次のようにします。

local ($var1, $var2, $var3);

括弧 ( ) でくくるんですね。この ( ) ですが、凄く重要です。忘れずに、( ) でくくるようにしましょう。 ( ) でくくるのを忘れるとどうなるかというと、エラーにはならないのですが、 1つ目の変数だけ local になって、2つ目から後ろの変数は local にならないのです! local にならないということはどういうことかというと、他の関数とか、 または呼び出し元の変数とかを壊してしまう可能性があるっていうことです。 複数の変数を local にするときは、( ) を忘れないっていうことを、お忘れなく!

関数の使い方

さあこうして、「ブラウザから送られてきたデータを返すgetformdata関数」が出来ました。 これをどうやって使うかというと、次のようになります。

$formdata = getformdata();

これで、送られてきたデータが取得できます。んーなんてシンプル、便利! これこそまさに関数です。 getformdata関数の中でどんなことが行われているのか、まったく知らなくても、 getformdata関数を呼び出す(という言い方をします)だけで、 送られてきたデータが分かっちゃうんですよ!素晴らしい。

作るもの

ここまででほとんど完成してますが、 getformdata関数を呼び出して、得られたデータを画面に表示するプログラムを作りましょう。

作成したCGIプログラム

getformdatatest.cgi
#!/usr/bin/perl

print "Content-type: text/html\n";
print "\n";

$formdata = getformdata();
print "formdata : $formdata";


sub getformdata
{
	local $formdata;
	if ($ENV{'REQUEST_METHOD'} eq "GET") {
		$formdata = $ENV{'QUERY_STRING'};
	}
	else {
		read(STDIN, $formdata, $ENV{'CONTENT_LENGTH'});
	}
	return $formdata;
}

実行結果

下の入力ボックスに文字列を入力して、送信ボタンを押してください。 別窓が開きます。

GETメソッドで送信
POSTメソッドで送信

考察

動きました

GETメソッドの場合も、POSTメソッドの場合も、ちゃんとデータが ブラウザで表示されました。成功です。 GETメソッドのデータの受信の仕方、 POSTメソッドのデータの受信の仕方、 この2つを一生懸命研究したんですが、 この関数があれば受信の仕方なんてまったく知らなくても データを受け取ることができるんですから、 まったく凄いものです関数というものは。

関数を置く位置

関数はsubというキーワードを使って作るとかそういうことは分かりました。 それじゃ、関数ってcgiファイルの中のどこにおけばいいんでしょうか? 上のプログラムでは、ファイルの一番最後に置いています。 他の場所じゃ駄目なんでしょうか?

答えは、どこでもいい、です。 cgiファイルは実行されるとファイルの先頭から1行ずつ処理されていきますが、 途中に関数があっても、その関数は実行されないで無視されるんです。 関数の中身は、その関数が呼び出されたときに実行されます。 今回作ったプログラムでは、「$formdata = getformdata();」のところで 初めてgetformdata関数が実行されます。この時点では、getformdata関数は まだ下の方にあるのでPerlインタプリタはgetformdata関数のことを知らないんじゃ? なんて思いましたが、 その辺はよく出来ていますよね。作る方は、関数を置く場所を気にする必要は無いです。

でも一般的に、関数はファイルの後ろの方に置くのが普通みたいですね。

$formdata変数のこと

プログラムでは、$formdata という変数が、関数の外と中の両方で出てきています。 これ、同じ名前の変数ですが、まったく別物ですよ。 関数の中で local で宣言していますから。

分かったこと

  1. 「もし〜なら」というのは if文で実現できます。
  2. 「もし〜なら〜そうでないなら〜」というのは if〜else〜で実現できます。
  3. 文字列が同じかどうか調べるには eq というものを使います。
  4. 関数は sub というキーワードで定義します。
  5. 関数は return 文で値を返すことができます。
  6. 関数の中でのみ使用する変数は local で宣言しておきます。
  7. 関数はファイルのどこに書いてもいいが、末尾の方に書くのが一般的です。
  8. ファイルはファイルの先頭から実行されるが、関数の中は関数を呼びださないと実行されません。
Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。