□Perl 講座 特別編 > Cookieの利用

◆Cookie(クッキー)

いよいよ特別編最後のクッキーの利用方法です。一度フォームに入力があった物を閲覧者のブラウザ側に記録しておいて、次回の入力からいちいち入力しないで済むようにするしようというものです。勿論その他いろいろな使い方が出来ると思いますが、記録の仕方を覚えることで自分なりに発展させていってください。但し、この機能が使えるのは相手方(閲覧者)がクッキーの利用(書き込み)を許可している場合です。
クッキーを利用する際に、必要になるサブルーチンは大きく別けて2つです。新しくクッキーに書き込むためのサブルーチンと、記録されているクッキーを読み出すサブルーチンです。

>Cookieの利用>第一段階

#クッキーの保存ルーチン
sub set_cookie { #1行目
  # クッキー60日間有効
  ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg)
  = gmtime(time + 60*24*60*60);

  $date_gmt = "$youbi, $mdayg\-$mong\-$yearg $hourg:$ming:$secg GMT";
  $cookies="name\:$FORM{'name'}\,email\:$FORM{'email'}";
  print "Set-Cookie: KAKISITI=$cookies; expires=$date_gmt\n";
}

上記のルーチンの簡単な説明をします。
#1行目・・・サブルーチンの開始
#2行目・・・コメント
#3行目〜4行目・・クッキーの有効期限を設定するために現在から
 60日後の日時の設定をしています。
 timeは現在でそれに60日*24時間*60分*60秒(60日間の秒数)を加算しています。
#6行目・・・得られた値を代入しています。
#7行目・・・クッキーに保存する内容を指定しています。
#8行目・・・クッキーへの書き込み処理です。
#9行目・・・サブルーチンの終了

※注意1
print "Set-Cookie: KAKISITI=$cookies; expires=$date_gmt\n";

KAKISITIは保存したクッキーを取り出すためのキーワード見たいな物です。任意につけてください。
expiresは保存しておく期日です。

※注意2
&set_cookie;(クッキーの保存ルーチンの呼び出し)は必ず、ヘッダの記述処理をおこなう前にしてください。ヘッダの記述に関してはこちらを参照してください。ですから、理想的な挿入方法としては
print "Content-type: text/html\n\n";
をメインルーチン内の&html;の直前に移動させましょう。

※注意3
説明上では名前とE-mailだけの保存処理を行っておりますが、もっといろいろな値を保存したい場合は適宜7行目を変更してください。但し、区切り文字「:」を使っていますので、保存内容に「:」が含まれる可能性があるのであれば、値を変換するか区切り文字の変更が必要です。

>Cookieの利用>第二段階

#クッキーの取得ルーチン
sub get_cookie { #1行目
    @pairs = split(/\;/, $ENV{'HTTP_COOKIE'});
    foreach $pair (@pairs) {
      local($name, $value) = split(/\=/, $pair);
      $name =~ s/ //g;
      $DUMMY{$name} = $value;
    }
    @pairs = split(/\,/, $DUMMY{'KAKISITI'});
    foreach $pair (@pairs) {
      local($name, $value) = split(/\:/, $pair);
      $COOKIE{$name} = $value;
    }

    $c_name  = $COOKIE{'name'};
    $c_email = $COOKIE{'email'};

    if ($FORM{'name'})  { $c_name  = $FORM{'name'}; }
    if ($FORM{'email'}) { $c_email = $FORM{'email'}; }
}

#1行目・・・サブルーチンの開始
#2行目・・・保存されているクッキー全てを配列@pairsに代入
#3行目〜7行目・・・保存されているクッキーをキーワードごとに値を指定します。
#8行目・・・キーワードとマッチするデータを@pairsに代入しなおし
#9行目〜12行目・・・データを分割し、記録されているname(名前)とemail(メール)の値を取得
#14行目〜15行目・・・得られた値を解りやすい変数に代入
#17行目〜18行目・・・フォームから新しく入力があった際、古いクッキーとの差し替え処理
#19行目・・・サブルーチンの終了

※注意1
14〜15行目は解りやすくするために行っている処理なので、なくても問題ありません。但し、その際は今後全ての変数名を$COOKIE{'name'}のまま利用するようにしてください。でないとおかしくなります。
※注意2
サブルーチンset_cookieでKAKISITIを変更した場合、例えばTESTにしたとき
print "Set-Cookie: TEST=$cookies; expires=$date_gmt\n";
サブルーチンget_cookieの8行目も変更しなくてはなりません。
@pairs = split(/\,/, $DUMMY{'TEST'});

>Cookieの利用>最後に

最後にクッキーを読み出された値がフォームに入力されるように準備しなくてはなりません。例えば今まで説明してきました、掲示板で言えば、新規投稿するためのフォームにそれぞれvalueを設定するだけです。不慣れなうちはややこしく感じると思いますし、思いのほか誤字とかで上手くいかないなどあるかもしれません。落ち着いて設定しましょう。

#ヘッダ部分プログラム
sub header {
    print <<"EOT";
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<TITLE>簡易掲示板</TITLE>
</HEAD>
<BODY>
<P>簡易掲示板</P>
<FORM action="bbs.cgi" method="POST">
<INPUT type="hidden" name="mode" value="write">
なまえ:<INPUT size="20" type="text" name="name" value="$c_name"><BR>
E-mail:<INPUT size="20" type="text" name="email" value="$c_email"><BR>
URL:<INPUT size="50" type="text" name="url" value="http://"><BR>
メッセージ:<BR>
<TEXTAREA rows="5" cols="50" name="msr"></TEXTAREA><BR>
<INPUT type="submit" value="投稿する"><INPUT type="reset" value="クリア">
</FORM>
<HR>
EOT
}

それぞれのルーチンの用意できたら、必要に応じてそれぞれのルーチンを呼び出せばOKです。具体的にどのタイミングで呼び出すか?という問題ですが、まず、set_cookieを呼び出すのは書き込まれた時に保存するわけですから、&write;を呼び出す直前に呼び出せば良い訳です。また、get_cookieについては新規投稿フォームが出力される前に呼び出すようにしてください。つまり、&header;を実行する直前に呼び出せば良い訳です。

なれちゃうとそんなに難しいことでは無いのですが、慣れるまでは本当に上手く使えません。(私がそうだっただけかも?(^-^;;)とにかくいろいろ試してみましょう!頑張ってください!
これにて、特別編を完結とさせていただきます。出来る限り配慮して執筆してはおりますが、不明な点や間違いなどあったかもしれません。今後も改善・修正など行っていきますが、何かお気づきの点がございましたら、ご一報いただけますと幸いです。

□特別編 一緒に簡易掲示板を作ってみよう