PHP:所有脚本中的ignore_user_abort(true)
我有一个在服务器端使用 PHP 的网站。
用户访问页面,PHP 进行一些计算,将数据写入 MySQL 数据库等。
想象一下,用户访问一个页面,PHP 为该用户创建一个帐户。创建过程由两部分组成:将注册数据插入到“users”表中,并将该帐户的设置插入到“settings”表中。这是两个必须依次执行的 SQL 查询。如果用户在第一次查询后退出页面,则不会在“设置”中插入任何值。
我怎样才能避免这个问题?我想简单地使用ignore_user_abort(true),对吗?
那么在每个 PHP 脚本的顶部调用ignore_user_abort(true) 不是很有用吗?我不知道在任何情况下它会引起问题。
I have a website which works with PHP on the server side.
Users access pages and PHP does some calculations, writes data to a MySQL database etc.
Imagine a user accesses a page where PHP creates an account for the user. The creation consists of two parts: inserting the registration data into the table "users" and inserting settings for this account into the table "settings". These are two SQL queries which have to be executed one after another. If the user quits the page after the first query, there aren't any values inserted into "settings".
How could I avoid this issue? I think simply by using ignore_user_abort(true), right?
So isn't it useful to call ignore_user_abort(true) on the top of every PHP script? I don't know any cases where it should cause problems.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于您的具体示例,使用数据库事务(如 Ignacio 提到的)将是更合适的方法。
不过,在其他情况下,您可能希望确保用户不能提前中止,但与数据库无关。例如,如果您更新数据库然后发送邮件,您不希望用户能够在邮件发出之前停止该过程。在这种情况下,
ignore_user_abort
比较合适。但是,请注意,由于客户端中止连接而导致的管道损坏不会立即停止执行,只会在您下次尝试写入脚本输出时停止执行。这可以通过调用
echo
或print
来实现,甚至可以通过关闭 PHP 标签并在打开新标签之前插入一些空格来实现(... ?> )。因此,如果您将脚本的所有“操作”部分都放在页面顶部,那么在尝试编写任何页面内容之前,您不必担心损坏的管道会影响您的应用程序逻辑。
当然,无论如何,您应该以这种方式将操作逻辑与页面内容分开。
来自 http:// php.net/manual/en/function.ignore-user-abort.php#refsect1-function.ignore-user-abort-notes
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
orprint
, 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
如果您需要多个查询完全发生或根本不发生,那么您应该使用事务正确地执行此操作,而不是解决问题。
例如,如果请求涉及冗长的计算并且用户决定他们根本不需要结果,则远程端可以方便地中止请求。
If you need multiple queries to either happen completely or not at all, then you should be doing it properly using transactions instead of putting a bandage on the problem.
It can be handy for the remote side to abort a request if e.g. the request involves lengthy calculations and the user decides that they don't need the results after all.
您可以在 php.ini 中设置
ignore_user_abort
: PHP.ini 配置不过,我不会这样做。我更愿意让 PHP 页面在命令行上启动另一个 PHP 实例,在后台进行查询,例如使用
exec
。此外,您的基本流程概念也可能存在偏差。如果用户中止计算的执行,您可能应该无论如何将其正确回滚 - 但这取决于正在执行的操作的性质。
You can set
ignore_user_abort
in php.ini: PHP.ini configurationI wouldn't do this, though. I would much rather have the PHP page start another PHP instance on the command line that does the querying in the background, e.g. using
exec
.Also, it could be that your basic flow concept is skewed. If the user aborts the execution of a calculation, you should probably roll it back properly anyway - but that depends on the nature of what is being done.