質問箱/4129

カテゴリ
サマリ#comment、 でIEの更新(再描画)ボタンを押すと二重投稿される
バージョン1.4.x
投稿者kahata
状態完了
投稿日2007-07-03 (火) 10:44:00

質問

拙作、自作プラグイン/include_module.inc.phpの使い方を模索しているkahataです。

プラグイン、#commentについて質問させていただきます。
コメントを投稿(挿入)した直後に、インターネットエクスプローラ等の更新(再描画)ボタンを押すと、情報の再送信を警告するポップアップが出て、再送信を強行すると以下のメッセージが出て二重投稿されてます。

練習ページ で【更新の衝突】が起きました
あなたがこのページを編集している間に、他の人が同じページを更新してしまったようです。
コメントを追加しましたが、違う位置に挿入されているかもしれません。

#articleでも同様の現象が起きますが、編集画面が出て二重投稿はされないようです。
投稿のときのpostをそのまま再送信しているためこの現象が起きると思うのですが、この二重投稿を防止する方法はないでしょうか? #commentなら二重投稿を削除すれば済みますが、一般的な掲示板等のアプリケーションでpukiwikiのpost,getを使う場合、更新ボタンを押す度に多重投稿になっては困ります。
色々コードをいじりましたが解決できません。
以下のコードが関係していると思いますが、ifの条件文の中身がよく理解できません。

	$title = $_title_updated;
	$body = '';
	if (md5(@join('', get_source($vars['refer']))) != $vars['digest']) {
		$title = $_title_comment_collided;
		$body  = $_msg_comment_collided . make_pagelink($vars['refer']);
	}

	page_write($vars['refer'], $postdata);

このコードの意味も併せてご教授下さい。宜しくお願いします。

回答

  • ちょうどこの辺りのソースを読んだところだったので、自分のまとめを兼ねて。間違っていたらご指摘下さい>詳しい方々 -- ぃぉぃぉ 2007-07-03 (火) 12:27:51
    • $title = $_title_updated;
      ページタイトル(標準スキンで一番上に表示されるやつ)を「~を更新しました」にする。
    • $body = '';
      エラーメッセージを空にする。(lib/pukiwiki.phpのretvarsにbody、msgがあると、エラー扱い)
    • if (md5(@join('', get_source($vars['refer']))) != $vars['digest']) {
      次の二つの比較。
      • md5(join('', get_source($vars['refer'])))
        現在のページのmd5ハッシュ(チェックサムの様なもの)。この時点でファイルから計算。
      • $vars['digest'])
        元のページのチェックサム。commentプラグインのあるページが表示された時点で計算されている。
    • $title = $_title_comment_collided;
      タイトルを衝突検出に。
    • $body = $_msg_comment_collided . make_pagelink($vars['refer']);
      本文を衝突検出に。
    • page_write($vars['refer'], $postdata);
      ページの更新。(wiki/以下のファイル更新)
  • 衝突時はpage_writeをやめてごにょごにょする、ってのは手ですね。 -- ぃぉぃぉ 2007-07-03 (火) 12:31:44
  • 強制的に書き込んでいるのは、
    ユーザーの行動
    (a)ページを開く
    (b)ページを読んでコメントを入力する
    (c)コメント挿入ボタンを押す
    で、(b)の間に他にコメントが入ったりページが更新されても、プラグインは(c)でソース読み直すので、衝突はあってもコメントが書き込まれ、ユーザーの期待する動作になっているので良いでしょう。けれど、強制的に書き込まずに、差し戻す、もしくは確認画面を噛ませる、という案も受け入れられると思います。(書き込み後にページを更新して、同じコメントが追加されなくなる。) -- ぃぉぃぉ 2007-07-03 (火) 13:03:25
    • 蛇足ですが、独立したアプリ(モジュール)の場合、人が編集中の時に他人が編集できないようロックしたりするのは、そのアプリの仕事でwikiの仕事ではありません。今ちょっと思い出したもので・・・ --kahata 2007-07-03 (火) 20:04:02
  • ありがとうございます。ということは、(日本語で言うと文字通り)postする人が最初にそのページを開いた時と、postした時点で(誰かが書き込んで)ページの内容が異なっていれば、collidedの警告を発しなさいということですね。このアルゴリズムによると何れにせよ(同じであっても異なっていても)post値が強制的にページに書き込まれます。
    仰るとおりページ内容が異なっていた場合writeを止めるのは#commentでは可能かもしれません。しかし一般掲示板ではpostデータをファイルに書き出すので検出が難しいです。端的に言えば同じposterがブラウザ更新ボタンを何回も押して同じpostデータを発信しているのを事前に検出したいのですが、このようなことは可能でしょうか。postの処理を行う前にsubmitのvalue値を''にしたりしてみましたがうまくいきません。 -- kahata 2007-07-03 (火) 12:49:02
  • postデータはブラウザ内に保存されているので難しいでしょうね...。って、そうか、書き込みシリアル番号を発行してpostデータに埋め込むとか...?
    それよりも、dev:BugTrack2/239この案2はだめ? -- ぃぉぃぉ 2007-07-03 (火) 13:15:21
    • dev:BugTrack2/239この案2みました。何となくですが?下記で言っているperl/cgiに近いような気がします。ヒントありがとうございます。--kahata 2007-07-03 (火) 13:59:02
  • ちょっとヒントになりそうなのは、perl/cgi等ではscriptを最初から読み直して初期化しているようですがよく判りません。ちなみにwikiでもコメント投稿後に一旦別ページを開いて、また#commentのページに戻ると、今度は何度更新ボタンを押しても多重書き込みは起こりませんが、、、 --kahata 2007-07-03 (火) 13:13:02
  • ぃぉぃぉさんありがとうございました。 dev:BugTrack2/239早速試みてうまくいきました。 ページを読み直しているわけですから、まさにcgi/一般phpで採られている方法で、この方法だと情報再送信の警告も出ません。これでpost/getを使った一般的アプリケーションをwiki上で実行できるようになりそうです。『なにもここまでしなくとも cgiのサイトを#iframeか外部リンクで引っ張ってくればよいじゃないか』との声が出そうですが、wiki応用の範囲が広がるだけでも意味があると思います。 -- kahata 2007-07-03 (火) 14:41:17
  • 一応解決しましたが、他にもアイデアがあるかも知れません。また他の方の参考になるかもしれませんので、私としてはしばらく質問のまま残しておきます。 -- kahata 2007-07-03 (火) 14:55:47
  • 自作プラグイン/include_module.inc.phpに同梱したサンプルのコメントモジュールを更新しました。 -- kahata 2007-07-03 (火) 16:38:46
  • 解決おめでとうございます。お役に立ってよかったです。
    ステータスを「完了」にしておいても他の方の参考になりますので、解決したら完了にして頂きたいです。具体的な要望・疑問があるのであれば、「質問」のままで良いと思います。(その際はその内容も記載して下さいね。) -- ぃぉぃぉ 2007-07-03 (火) 18:02:53
    • 了解しました。 ありがとうございました。-- kahata 2007-07-03 (火) 18:08:42

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-03-20 (金) 19:20:19
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.358 sec.

OSDN