12

我有一个在服务器端使用 PHP 的网站。

用户访问页面,PHP 进行一些计算,将数据写入 MySQL 数据库等。

想象一个用户访问一个页面,PHP 为该用户创建了一个帐户。创建由两部分组成:将注册数据插入“users”表中,并将该帐户的设置插入“settings”表中。这是两个必须一个接一个地执行的 SQL 查询。如果用户在第一次查询后退出页面,则“设置”中不会插入任何值。

我怎样才能避免这个问题?我认为只需使用 ignore_user_abort(true),对吗?

那么在每个 PHP 脚本的顶部调用 ignore_user_abort(true) 不是很有用吗?我不知道它应该引起问题的任何情况。

4

3 回答 3

14

For your specific example, using database transactions (as mentioned by Ignacio) would be the more suitable approach.

There are other cases where you might want to make sure the user can't abort early, though, not relating to databases. For example, if you update the database and then send out a mail, you don't want a user to be able to stop the process before the mail goes out. In this sort of case, ignore_user_abort would be appropriate.

However, note that a broken pipe due to client aborting the connection doesn't stop execution right away, only at the point you next try to write to the script output. This can be through calling echo or print, or even just by closing the PHP tag and inserting some whitespace before opening a new one (... ?> <?php ...). So if you have all the ‘action’ part of your script at the top of the page, before you try to write any page content, you don't have to worry about interruptions from broken pipes affecting your app logic.

And of course you should be separating action logic from page content in that way anyway.

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

PHP will not detect that the user has aborted the connection until an attempt is made to send information to the client. Simply using an echo statement does not guarantee that information is sent

于 2010-03-07T18:32:58.397 回答
1

如果您需要多个查询完全发生或根本不发生,那么您应该使用事务正确地完成它,而不是在问题上贴上绷带。

如果请求涉及冗长的计算并且用户决定他们根本不需要结果,则远程端可以方便地中止请求。

于 2010-03-07T17:27:07.413 回答
1

可以ignore_user_abort在 php.ini 中设置:PHP.ini 配置

不过,我不会这样做。我宁愿让 PHP 页面在命令行上启动另一个 PHP 实例,该实例在后台进行查询,例如使用exec.

此外,您的基本流程概念可能存在偏差。如果用户中止计算的执行,您可能应该正确回滚它 - 但这取决于正在执行的操作的性质。

于 2010-03-07T17:27:26.840 回答