Perl/CGI研究室 'PERL-LABO'

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

クッキー処理汎用関数の作成

研究内容

クッキーの書き込み、読み込みを処理する関数を作成します。

詳細

クッキーを処理する関数を作る理由

クッキーは1つの文字列です。 データが1つだけのときは、そのデータを直接クッキーに書き込んでおけばいいので 処理は簡単です。でもデータが複数あるときは、どうしたらいいのでしょうか。 複数のデータを扱うのに便利なものといえば、アレです。連想配列です。 ですから、クッキーを連想配列にする、連想配列をクッキーに書き込むという 処理をする関数を作ったら便利じゃないかな、と考えました。

結果

クッキー書き込み関数

クッキーの書き込みは、HTTPヘッダの Set-Cookie で行います。 ですので、クッキーを書き込む関数の仕様としては、次のようなものが考えられますね。

(1) Set-Cookie: 〜 という行を print 文で出力する
(2) Set-Cookie: 〜 という行を文字列にして返す
(3) Set-Cookie: 〜 の 〜 の部分を文字列にして返す

(2) と (3) は、クッキーの設定をHTTPヘッダの Set-Cookie で行うっていうのを知っていないと クッキーの処理ができません。 せっかく関数にするんだから、できるだけ使うのが簡単なものに したいですね。(1) の場合は、「HTTPヘッダを出力するときにその関数を呼び出さなければいけない」 という条件がつきますが、中では一番楽なような気がします。ですから (1) のような関数を作りましょう。

この関数は、クッキーに書き込む内容を連想配列で受け取ります。 あと必要なデータとしては、クッキーの有効期限があります。 ですので、関数の引数は (有効期限, 連想配列) としましょう。

関数の中では、まず Set-Cookie: を出力して、 その後 キー<>データ という形で連想配列の内容を <> 区切りで出力して、 最後に有効期限文字列を出力する、というものです。 今までの知識で作ることができました。

クッキー読み込み関数

連想配列の内容が、キー1<>データ1<>キー2<>データ2<>… という形で クッキーに書き込まれていますので、これをばらばらにして連想配列に入れて、 その連想配列を返す関数です。これも今までの知識で作ることができました。

作成したCGIプログラム

writecookietest.cgi (クッキー書き込みテスト)
#!/usr/bin/perl

require 'cookie.pl';

$cookie{'key1'} = "cookie1";
$cookie{'key2'} = "cookie2";

plab::setcookie(0, %cookie);

print "Content-type: text/html\n";
print "\n";
print "書き込みました。";
readcookietest.cgi (クッキー読み込みテスト)
#!/usr/bin/perl

require 'cookie.pl';

%cookie = plab::getcookie();

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

foreach (keys(%cookie)) {
	print "$_ = $cookie{$_}<br>"; 
}
cookie.pl (クッキー処理関数ライブラリ)
package plab;

# クッキーの書き込み
# 引数 (有効期限, 連想配列)
# 有効期限は経過時間で与えます。0のときは有効期限設定無しになります。
# HTTPヘッダを出力するのでHTTPヘッダ出力の最初などに呼びます。
# <> を含むデータを書き込むとおかしなことになります。
sub setcookie
{
	local($n, $i);
	local $expire_delta_hour;
	local($expires, @t, @m, @w);

	$n = @_;
	$expire_delta_hour = $_[0];

	# 有効期限文字列の作成
	if ($expire_delta_hour != 0) {
		@t = gmtime(time() + $expire_delta_hour*60*60);
		@m = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
		@w = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
		$expires = sprintf(" expires=%s, %02d-%s-%04d %02d:%02d:%02d GMT;",
				$w[$t[6]], $t[3], $m[$t[4]], $t[5]+1900, $t[2], $t[1], $t[0]);
	}

	# クッキーを出力します
	# キー<>データ<>キー<>データ… という形になります
	print "Set-Cookie: ";
	for ($i = 1; $i < $n; ++$i) {
		print "$_[$i]";
		if ($i != $n - 1) {
			print "<>";
		}
	}
	print ";$expires\n";
}

# クッキーの読み込み
# 連想配列を返します
sub getcookie
{
	local $cookie;
	local %cookies;
	local @data;
	local($n, $i);

	$cookie = $ENV{"HTTP_COOKIE"};	
	@data   = split('<>', $cookie);

	$n = @data;
	for ($i = 0; $i < $n; $i += 2) {
		$cookies{$data[$i]} = $data[$i + 1];
	}

	return %cookies;
}

1;

実行結果

クッキーを書き込みます。
クッキーを読み込みます。

考察

動きました

無事、動きました。 これで、クッキーを使って複数のデータを処理したいときなんかに楽ができそうですね。

例えば、前回の訪問日時と訪問回数をクッキーを使って処理するとしましょう。 その場合は、連想配列を使って、次のようにアクセスすることでこれらを 簡単に扱えるようになります。

%cookie = plab::getcookie();

	$cookie{'前回の訪問日時'}、$cookie{'訪問回数'}を使ってなんか処理する

plab::setcookie(〜, %cookie);

なかなかよさげじゃないですか? 今までもそうでしたが、こうやって関数にすると、クッキーの処理の仕方の細かいこととか 忘れちゃっても平気っていうのが嬉しいですね。

なお、setcookie 関数の第一引数に 0 を指定した場合は、 有効期限を設定しなかったのと同じになります。つまり 有効期限はブラウザを閉じるまでになります。 あと、データの区切りに <> を使っているため、データの中に <> があるとおかしなことに なってしまいます。その辺はご愛嬌…

これで一段落?

これでクッキーの研究も一段落でしょうか。 クッキーに関してはまだ研究していないものもありますが、 今回の研究でなかなか実用的な関数の作成ができたと思います。

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

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