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