• 締切済み

リロード対策について困っています

本の貸出システムを作っていまして、貸出処理も返却処理も作成し、本の貸出登録後、F5キーなどを押すと「このページを再表示するには以前送信した~~~」とアラートが出て、「再試行」をクリックすると返却処理をしてしまうのですが、これを誤って「再試行」押してしまっても貸出処理を行わないようしたいのですが、どのようにしたら良いのでしょうか?また、別の方法はありますでしょうか? 必要があればソースコード載せます。 上司の方から「CGIが全く同じパラメータで連続して呼ばれるわけですから、CGI側で前どんな処理をしたかを覚えておけば、2度目以降をはじくことはできるはずです。」と言われたのですがそのやり方が良く分かりません。 あとかろうじてリロード対策でWalrus::Session::Liteを使うという所まで分かり、一応試しに​http://d.hatena.ne.jp/d4-1977/20050706/1120670844​のと同じサンプルを作ってみたのですが、15行目のmy @ID = tied(%session_data)->list_session_id; の所でエラーで引っかかりCan't call method "list_session_id" on an undefined value at /usr/local/apache2/cgi-bin/test.cgi line 15, <DATA> line 64. というエラーを吐き出すのですが、経験者の方で原因がお分かりになる方はいらっしゃいますでしょうか?

みんなの回答

  • kt_yuka
  • ベストアンサー率53% (8/15)
回答No.1

気軽に答えてるので参考程度にしてください。 えっと、貸出登録後にリロードすると返却処理をするということは、 貸出処理と返却処理は同じロジックを使ってるってことですかね? 「貸し出されてた場合は返却、返却されている場合は貸出」なのかな? ご指定のようにセッションに保存してチェックしても良いでしょうし、 最初の処理の前に一意のキーみたいなものを用意できるのであれば、 そのキーが一致した場合には処理しない、みたいにもできるでしょう。 (その処理以前に生成しないと、リロードで別のキーが生成されちゃいますけど) で、私のよくやる回避策ですが、 貸出処理を行った後、Locationを別の画面、例えば「完了しました」と表示 するだけの画面にとばしちゃいます。で、この画面では何の処理もしません。 この画面をリロードしても何の問題も無いですからね。 Walrus::Session::Lite は、ちょっと使ったことありましたけど忘れちゃいました。 ごめんなさい。 他にもCGI::SessionやApache::Sessionも探してみてください。 ちなみに私は上記3つとも、アクセスが集中した時に誤動作を起こしたので、 セッション管理は自前でシンプルに行ってます。

nardobrea
質問者

補足

kt_yuka様ありがとうございます。 >>貸出処理と返却処理は同じロジックを使ってるってことですかね? という事ですが貸出中か貸出可能かという「状態」という列を作成してものをDB登録させてif文で状態が貸出中なら返却処理を貸出可能なら貸出処理をしているという状況です。 また、別の方法でフラグを立てるやり方もあるみたいで、 最初の状態=まだ押していない状態=貸し出し処理をしていない、 DBは貸し出しフラグ「0」の状態のはず。ここでボタンが押されたら、貸し出し処理。貸し出しフラグ「1」を記録する。 ここで、ユーザーが2度押しというか更新ボタンを押したとする。 しかし、DBには貸し出しフラグ「1」がすでに記録されているはず。 だから、「あなたはもう借りてるよ」とか出して やればいい。みたいな事も言われましたが、自分の書いたコードでは全く意味がなく歯が立たないです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • CGIについて

    会社から以下のようなcgiを作ってくれと言われましたが、初心者の為皆目見当つかない状態です perl,c,c++のうちなんでもいいそうですが、perlが入っているので、それを使おうかと思っています。 <図書管理サイト(CGIプログラム)要求仕様> rental.cgi 1.登録社員がアクセス、セレクトボックスから自分を選択し、パスワードを入力。  (パスワードは当面、社員番号と同じでよいと思われる) 2.認証に成功すると図書リスト画面が出る。図書リスト画面は、  「図書テーブル」の内容がリスト表示される。表示は「登録日が新しい順」。  本が増えることを想定すると、図書名による「検索」ができるとなおよい。 3.「貸し出し中ではない」本は、「借りる」といるリンクがつく。「借りる」を  クリックすると、JavaScriptによるアラートで「本XXXXを借りますか?」と出す。  OKがクリックされたら、貸し出し登録。  データベースの更新等貸し出し処理が無事終了したら  該当の本を「貸し出し中」とし、図書リストを更新表示。  なお、この時プログラム内部で「履歴テーブル」にデータを追加しておくこと。 4.図書リスト画面において、該当社員が借りている本の場合は「借りる」ではなく  「返却する」リンクとなる。  クリックすると、JavaScriptによるアラートで「本XXXXを返却しますか?」と出す。  OKがクリックされたら、図書返却登録。3.と逆のステップになる。  データベースの更新等返却処理が無事終了したら  該当の本を「貸し出し中」では無くし、図書リストを更新表示。  なお、この時成功画面に「本は棚に忘れず返却してください」などと出す。 データベースの方はpostgreSQLで下のような感じで作ってあります。 データベース名…bookmanagement bookmanagement=# CREATE TABLE books( bookid text, --本ID bookname text, --本名称 author text, --著者 explanation text, --説明 date date, --登録日 lending text, --貸出中? finallending text, --最終貸出日 lendinguserid text  --最終貸出ユーザID ); CREATE TABLE bookmanagement=# CREATE TABLE usertable( userID text, --ユーザID(社員番号) name text, --ユーザ名 pass text, --パスワード post text --所属部署 ); bookmanagement=# CREATE TABLE logtable( logID text, --<履歴ID><ユーザーID> date timestamp,<発生日時(=貸出日時)> bookid text,<本ID> userID text --<ユーザーID> );

    • 締切済み
    • CGI
  • 管理ファイル(?)の作成

    図書館の本のような管理システムをゼロから作成したいです。 貸出日、貸出相手先、返却日、未返却リスト(本と貸出先)がすぐにわかるようにしたいです。 エクセル、アクセス、どちらが便利ですか? ちなみにデータ数は、貸出先が30程度、本の種類は600程度です。 これ以上増える予定はありません。 参考になるようなサイトがあれば教えていただければ助かります。 よろしくお願いします。

  • Access テーブルのデータをフォーム上で、検索したい

    こんにちは。Access で簡単な貸出管理データを作っています。 現在、貸出フォームは作ったのですが、 返却フォームを作る際、 今度は、一度テーブルに保存した貸出記録データを 返却フォームで検索して、表示したい場合、どのように したらよろしいでしょうか? 貸出フォームでは、 テーブル1、社員ID、氏名、電話番号 テーブル2、備品ID、備品名、貸出日、返却予定日、 社員ID、氏名、電話番号 これをサブフォームを使ってつくりました。 このテーブル2のデータを返却フォームで検索して、 (備品IDか社員IDで) 表示させたいと思っています。 よろしくお願い致します。

  • 月毎、日別に条件に当てはまるレコードを抽出したい。

    visual web developer で貸し出し表を作成しています。 sqlサーバーの予定テーブルに下記のようなデータが入っています。 ID  貸し出し日  返却予定日  貸し出した物 1   2010/03/31  2010/04/03  本 2   2010/04/02  2010/04/02  DVD 3   2010/04/02  2010/04/03  CD 上記のデータで4月に貸し出しを行っている毎日の状況を抽出するにはどのようなsql文を書けばよろしいでしょうか。 下記のような結果を期待しています。 日付      ID    貸出日   返却予定日   貸し出した物 2010/04/01  1    2010/03/31 2010/04/03   本 2010/04/02  1    2010/03/31 2010/04/03   本 2010/04/02  2    2010/04/02 2010/04/02   DVD 2010/04/03  1    2010/03/31 2010/04/03   本 2010/04/03  3    2010/04/02 2010/04/03   CD 2010/04/04 2010/04/05 2010/04/06 2010/04/07 ..... 2010/04/30 予定テーブルに対して「貸出日が2010/04/30以下」 or 「返却予定日が2010/04/01以上」のwhere条件で 4月の予定を抽出する事は出来ますが、複数貸し出しがある日を複数行で返し、無い日についてもNULLを返すやり方が思いつきません。 どのようなsql文を書けばよろしいでしょうか。 宜しくお願いいたします。

  • perlにおけるセッションIDについて

    sessionIDがページを更新するたびに変わってしまいます。 その結果、前回セッションに保存した値を読み込めません。 my $cgi = new CGI; CGI::Session->name("SESSION_ID"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); print $session->header(-charset=>'UTF-8'); print $session->id(); print $session->param("name"); #表示されず。 というようにしてセッションIDを表示すると、毎回変化します。 どうしたらIDを変わらないように出来るでしょうか? ちなみに、セッションに書き込むのは、 my $cgi = new CGI; CGI::Session->name("SESSION_ID"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); $session->header(-charset=>'UTF-8'); $session->param("name", "abc"); $session->flush(); undef($session); こんな処理をしてます。

    • ベストアンサー
    • Perl
  • セッションデータの排他処理

    セッションデータを更新するようなケースで、簡単に排他処理をする方法はないでしょうか。 現在はCGI::Sessionを使っていますが、このfileドライバは、読み込み時にflock⇒開放⇒書き込み時にflock、というように一度開放してしまいます。他の付属ドライバは調べていませんが同じかもしれません。 CGI::Sessionオブジェクトが存在する間はずっとロックしておいて欲しいのです。(と言うより普通に考えればそうであるべきな気がしますが) やはりそのための、たとえばIDごとにわざわざロックファイルを作るとかの処理が必要なのでしょうか。あるいは、ドライバを自分で書くとか。 常套手段的な、それともすでにそういうドライバをご存知でしたら教えてください。 また、セッションデータを更新するなんて珍しくもないと思うんですが、CGI::Sessionが対応してない理由とか、皆さんはどうしているのかも、気になります。

  • hiddenを使ったセッション

    こんにちは。 セッションを使ったデータの受け渡しをしたいのですが、 (携帯を考慮してcookieは使わないやり方で) hiddenにセッションIDを持たせる方法で書いてみたのですが、 うまくいきません。 送られてはいるけど、受け取れていないのかな…? とは思うのですが、対処がわかりません。 以下のソースです。(確認用でGETにしてます) 望むのは、printされたセッションIDとテキスト内のセッションIDが 同一になる(=セッションが保持できてるということですよね?) かつ、submitしても、セッションIDが変わらない、という状況です。 よろしくお願いいたします。 print "Content-type: text/html\n\n"; use CGI; use CGI::Session qw/-ip-match/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'}); } else { $query_string = $ENV{'QUERY_STRING'}; } my $cgi = new CGI; CGI::Session->name("session_id"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); $sid = $session->id(); $session->param('value', $sid); $sesid = $session->param('value'); print $sesid."<br>\n"; undef($session); @query = split(/&/, $query_string); foreach $query (@query){ ($name, $data) = split(/=/, $query); $data{$name} = $data; } print <<"EO"; <html><head> <title> </title> </head> <body><hr><hr> <form action="./test.cgi" method="GET"> <input type="hidden" name="session_id" value="$sesid"> <input type="text" name="btn" size="50" value="$data{'session_id'}"><br> <input type="submit" value="submit"><br> </form> <hr><hr></body></html> EO

  • CGI::Session

    http://perldoc.jp/docs/modules/CGI-Session-3.11/Session.pod 上記サイトを参考に、 use CGI::Session; my $session = new CGI::Session("driver:File", undef, {Directory=>'/tmp'}); my $CGISESSID = $session->id(); を稼動中の掲示板CGIに組み込んでみたところ、$session がnullになるようで、$session->id()のところでエラーになってしまいます。 (use CGI::Session;の行ではエラーにはなりません。) ■driver:Fileをdriver::Fileにしてみました。 ■driver:Fileをundefにしてみました。 ■my $query = new CGI;を追加し、 newの2番目の引数を$queryにしてみました。 ■tmpディレクトリの属性を744、766、777にしてみました。 ■/tmp を ./tmpにしてみました。 上記、いずれも同じ結果になってしまいました。 何がいけないのかわかりません。ファイルの構成は下記のようになっています。 /test.cgi /tmp /CGI/Session.pm /CGI/Session/ErrorHandler.pm アドバイスなどありましたら、よろしくお願いします。

  • セッションデータの使い方など

    http://perldoc.jp/docs/modules/CGI-Session-3.11/Tutorial.podを読みながら、セッションについて勉強しています。セッションIDはだいたい理解しました。セッションデータは、具体的にどのようなデータが格納され、どのように使用するものなのでしょうか?

    • ベストアンサー
    • CGI
  • 続Gecko エンジンでの Location ヘッダについて

    Gecko エンジンでの Location ヘッダについて http://oshiete1.goo.ne.jp/qa4227374.html の続きです。 なんだかよく分からない状況になったのでより実際の処理とほぼ同様の 処理を行っているサンプルを用意しました。 # セッション管理 use strict; use CGI::Session; &main(); # メイン sub main { my $cgi = &getreq(); print "Pragma: no-cache\n"; print "Cache-Control: no-cache\n"; # セッション取得 my $session = &session($cgi); # セッションが取得できない場合、再取得 if($session == undef) { # print "Content-type: text/plain\n\n"; # print "CGISESSID=$cgi->{'CGISESSID'}\n"; $session = &session({}); # セッション ID を取得してリダイレクト my $id = $session->id(); print "Location: ./?CGISESSID=$id\n\n"; exit; } my $id = $session->id(); if($cgi->{'CGISESSID'} eq '' || $cgi->{'CGISESSID'} ne $id) { # print "Content-type: text/plain\n\n"; # print "CGISESSID=$cgi->{'CGISESSID'}\n"; # セッション ID が指定されていないまたは # セッション ID が異なる場合リダイレクト print "Location: ./?CGISESSID=$id\n\n"; exit; } print "Content-type: text/plain\n\n"; print "CGISESSID=$id\n"; print "OK\n"; exit; } # CGI リクエストの取得 sub getreq { my $cgi = {}; my $query = ''; $query = $ENV{'QUERY_STRING'}; my @args = split(/&/, $query); foreach my $i (@args) { my ($name, $val) = split(/=/, $i); $val =~ tr/+/ /; $val =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $name =~ tr/+/ /; $name =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $cgi->{$name} = $val; } delete($cgi->{''}); return $cgi; } # セッション取得 sub session { my $cgi = shift; my $dir = { 'Directory' => 'tmp' }; CGI::Session->find(undef, sub {}, $dir); if($cgi->{'CGISESSID'} eq '') { my $session = new CGI::Session(undef, undef, $dir); $session->expire("1h"); return $session; } my $session = CGI::Session->load(undef, $cgi->{'CGISESSID'}, $dir); return ($session == undef || $session->id() eq '') ? undef : $session; } こんな感じのCGIで以下のような状況の時にページを更新すると IE(Trident)/Opera(Presto)及びSafari for Win(WebKit)では 正常に動作するのですがFxやSeaMonkey(Gecko)ではおかしな動作を します。 1. セッションが切れた時 2. セッションファイルを手動で削除した時 具体的にはセッションが切れたら再度新しいセッションを作成して リダイレクトをするようにしてあるのですがGeckoでは一度セッションが 切れると更新する度に新しいセッションを作成するようになってしまい ます。 以前の質問の回答のように Status: 303 See Other ヘッダを出力して 見たのですがやはり効果はないようです。 Cookieは使いたくないのでセッションID(sesid)をCGIリクエストで 送信しているのですがこの方法がまず問題なのでしょうか。 他にも問題のある部分がありましたらご指摘お願いします。

    • ベストアンサー
    • CGI