12

サーバー側で PHP を使用する Web サイトがあります。

ユーザーがページにアクセスすると、PHP が何らかの計算を行い、データを MySQL データベースに書き込みます。

PHP がユーザーのアカウントを作成するページにユーザーがアクセスするとします。作成は、登録データをテーブル「users」に挿入することと、このアカウントの設定をテーブル「settings」に挿入することの 2 つの部分で構成されます。これらは、次々に実行する必要がある 2 つの SQL クエリです。ユーザーが最初のクエリの後にページを終了した場合、「設定」に挿入される値はありません。

この問題を回避するにはどうすればよいですか? 単純に ignore_user_abort(true) を使用すると思いますよね?

では、すべての PHP スクリプトの先頭で ignore_user_abort(true) を呼び出すと便利ではないでしょうか? 問題が発生するケースはわかりません。

4

3 に答える 3

14

特定の例では、(Ignacioが述べたように)データベーストランザクションを使用するのがより適切なアプローチです。

ただし、データベースとは関係なく、ユーザーが早期に中止できないようにする必要がある場合もあります。たとえば、データベースを更新してからメールを送信する場合、メールが送信される前にユーザーがプロセスを停止できないようにする必要があります。この種の場合、ignore_user_abortが適切でしょう。

ただし、クライアントが接続を中止したためにパイプが壊れても、すぐに実行が停止するわけではなく、次にスクリプト出力に書き込もうとした時点でのみ停止することに注意してください。echoこれは、またはを呼び出すことによってprint、またはPHPタグを閉じて、新しい空白を開く前に空白を挿入することによっても可能です(... ?> <?php ...)。したがって、スクリプトのすべての「アクション」部分がページの上部にある場合は、ページコンテンツを書き込もうとする前に、壊れたパイプによる中断がアプリのロジックに影響を与えることを心配する必要はありません。

そしてもちろん、とにかくそのようにアクションロジックをページコンテンツから分離する必要があります。

http://php.net/manual/en/function.ignore-user-abort.php#refsect1-function.ignore-user-abort-notesから

PHPは、クライアントに情報を送信しようとするまで、ユーザーが接続を中止したことを検出しません。エコーステートメントを使用するだけでは、情報が送信されることは保証されません。

于 2010-03-07T18:32:58.397 に答える
1

複数のクエリが完全に発生するか、まったく発生しない必要がある場合は、問題に包帯を巻くのではなく、トランザクションを使用して適切に実行する必要があります。

たとえば、リクエストに長い計算が含まれていて、結果が必要ないとユーザーが判断した場合などに、リモート側でリクエストを中止すると便利です。

于 2010-03-07T17:27:07.413 に答える
1

php.ini で設定できますignore_user_abort: PHP.ini 構成

しかし、私はこれをしません。むしろ、コマンド ラインで PHP ページに別の PHP インスタンスを開始させて、バックグラウンドでクエリを実行させたいと考えていますexec

また、基本的なフローの概念が歪んでいる可能性もあります。ユーザーが計算の実行を中止した場合は、とにかく適切にロールバックする必要がありますが、それは実行中の処理の性質によって異なります。

于 2010-03-07T17:27:26.840 に答える