占いページを作ってみる(8) cookieを利用して情報を保存する

これまでに、

  • 星座を選ぶセレクトボックスと、ボタンがあるフォーム
  • ボタンを押したら、占い結果が表示されるロジック

を作ってきました。
今のままでも、ボタンを押せば占い結果が表示される占いページになっていますが、できれば一度選択した星座は覚えていて欲しいですよね。何度も選びなおさないといけないのは面倒です。
それに今、ネットで公開されているWebサービスのほとんどは、そういうことができるようになっているので、できないサイトには利用者は違和感を覚えるでしょう。最低限、利用者が当たり前だと期待するような動作は作っておかなければなりませんよね。
というわけで、星座の情報をcookieを利用してブラウザに保存しておきます。これもCGI.pmモジュールを利用すれば簡単です。

#!/usr/local/bin/perl
use strict;

use CGI;

my $q = CGI->new();

my $uranai = $q->param('uranai');

#星座取得
my $seiza = $q->param('seiza');
$seiza = $q->cookie('seiza') if !defined $seiza;
my %seiza_selected = ($seiza => 'selected');

use lib qw(./);
use MyUranai;
my $myUranai = MyUranai->new();

#「占う」ボタンが押されたら
my $uranai_html;
if($uranai){
	#占いの結果を作成する
	my $uranai_kekka = $myUranai->getUranaiText();
	$uranai_html = <<"URANAI_END";
<div id="kekka">
<h2>占い結果</h2>
$uranai_kekka
</div>
URANAI_END
}

#cookie保存は一ヶ月
my $cookie = $q->cookie(-name =>'seiza', -value =>$seiza, -expires=>'+1M');

#ここから、HTMLページ
print $q->header(-charset=>'UTF-8', -cookie=>$cookie);

print <<"HTML_END";
<html>
<head>
<title>占いページ</title>
</head>
<body>
<h1>占いページ</h1>
<form method="POST">
あなたの星座は?
<select name="seiza">
<option value="0" $seiza_selected{'0'}>おひつじ座</option>
<option value="1" $seiza_selected{'1'}>おうし座</option>
<option value="2" $seiza_selected{'2'}>ふたご座</option>
<option value="3" $seiza_selected{'3'}>かに座</option>
<option value="4" $seiza_selected{'4'}>しし座</option>
<option value="5" $seiza_selected{'5'}>おとめ座</option>
<option value="6" $seiza_selected{'6'}>てんびん座</option>
<option value="7" $seiza_selected{'7'}>さそり座</option>
<option value="8" $seiza_selected{'8'}>いて座</option>
<option value="9" $seiza_selected{'9'}>やぎ座</option>
<option value="10" $seiza_selected{'10'}>みずがめ座</option>
<option value="11" $seiza_selected{'11'}>うお座</option>
</select>
<input type="submit" name="uranai" value="占う">
</form>
$uranai_html
</body>
</html>
HTML_END

今回は、cookieの利用と、フォームのセレクトボックスで星座情報が最初から選ばれた状態にする処理を追加しました。

#星座取得
my $seiza = $q->param('seiza');
$seiza = $q->cookie('seiza') if !defined $seiza;

フォームから送られてくる、利用者が選んだ星座情報が無い場合(つまり、最初にページが表示された時)、cookieに保存されている星座情報が$seizaの値になるようにします。

my %seiza_selected = ($seiza => 'selected');

(略)

<option value="0" $seiza_selected{'0'}>おひつじ座</option>
<option value="1" $seiza_selected{'1'}>おうし座</option>
<option value="2" $seiza_selected{'2'}>ふたご座</option>
<option value="3" $seiza_selected{'3'}>かに座</option>
<option value="4" $seiza_selected{'4'}>しし座</option>
<option value="5" $seiza_selected{'5'}>おとめ座</option>
<option value="6" $seiza_selected{'6'}>てんびん座</option>
<option value="7" $seiza_selected{'7'}>さそり座</option>
<option value="8" $seiza_selected{'8'}>いて座</option>
<option value="9" $seiza_selected{'9'}>やぎ座</option>
<option value="10" $seiza_selected{'10'}>みずがめ座</option>
<option value="11" $seiza_selected{'11'}>うお座</option>

セレクトボックスを最初に選ばれた状態にするためには、星座のオプションタグにあらかじめselectedを追加します。ここでは連想配列を使って、選択された星座の値がキーに指定された場合だけselectedという文字の値がつくようにしました。

#cookie保存は一ヶ月
my $cookie = $q->cookie(-name =>'seiza', -value =>$seiza, -expires=>'+1M');

#ここから、HTMLページ
print $q->header(-charset=>'UTF-8', -cookie=>$cookie);

cookieCGI.pmモジュールのcookieメソッドを利用すれば、cookieの名前(-name)と値(-value)や保存期間(-expires)などを指定するだけで、cookieをブラウザに送信するのに必要な形式にしてくれます。これをそのままheaderメソッドに渡してやれば、一緒にヘッダとして送信してくれるわけです。
ちなみに、$cookie変数の中身は

seiza=11; path=/; expires=Sun, 18-Oct-2009 15:15:12 GMT 

みたいな感じになっていて、

print "Set-Cookie: $cookie;\n";

とやれば、そのままヘッダとしてcookieがセットされるわけですけど、普通はheaderメソッドに渡しますよね。
複数のcookieを送信したい場合には、

print $q->header(-charset=>'UTF-8', -cookie=>[$cookie1, $cookie2]);

という風に、配列のリファレンスを渡してやってくださいな。
保存期間1ヶ月にしたことには意味はありません。保存期間を指定しない場合は、ブラウザを閉じるとcookieは削除されるような動作になります。
-expiresの指定の仕方は以下のとおりです。

    +30s                              今から30秒
    +10m                              今から10分
    +1h                               今から1時間
    -1d                               昨日(つまり、できるだけ早く!)
    now                               直後に
    +3M                               3ヶ月間
    +10y                              10年間
    Thursday, 25-Apr-1999 00:40:33 GMT  指定された時刻と日付


これでやっと占いページっぽくなりましたね。
…占いテキストがどうやって選ばれているかは利用者にはわからないので、このままで良しにしちゃうのもアリですが、次回は星座情報を占い結果に活かす方法を考えたいと思います。