【问题标题】:Fatal error using session_start inside foreach (after migration)在 foreach 中使用 session_start 的致命错误(迁移后)
【发布时间】:2013-09-11 21:16:43
【问题描述】:

问题是从什么时候开始的?

我的托管服务提供商不得不像一周前一样将我的网站更改为另一台服务器。从那以后,我的一个脚本抛出了一个错误。由于在更改之前一切正常,我假设代码最初是正确的,所以我很困惑为什么会发生这种情况,我希望你能尝试让我朝着好的方向发展。

代码

出现问题的代码如下:

session_start();
   $items=$_SESSION['items'];
   $_SESSION['numItems']=0;
session_write_close();

foreach($items as $num => $currentItem){

   //here I work with $currentItem...

   session_start();//starting error line
      $_SESSION['numItems']++;
   session_write_close();
}

session_start();
   unset($_SESSION['numItems']);
session_write_close();

错误

如果我运行代码,我会收到一个 PHP 致命错误:在注释为启动错误行的行中超过了 30 秒的最大执行时间。

现在,最奇怪的是,如果我检查 $_SESSION['numItems'] 的值,当数组 $items 的元素不能超过 250 个时,它可以达到 12500(或更多)。所以有些东西正在创造一种无限循环!

需要考虑的事项

  1. 如果我注释掉 foreach 结构内的三个会话行(或者我将它们移到外面),一切正常。

  2. 如果我只注释掉这些行中的第二行,问题仍然存在。

  3. 相同的代码结构,但使用 while 而不是 foreach 在同一服务器上的另一个脚本中工作。

  4. 我的托管服务提供商无法告诉我我拥有哪个 PHP 版本和配置。现在,版本是 5.2.17。

感谢您的帮助!

编辑:

因为它引起了很多混乱:

代码结构打开和关闭会话,因为这样我可以从第二个文件中读取会话变量,并让用户更新执行进度。第二个文件每 2 秒读取一次 $_SESSION['numItems'],并关闭与 session_write_close(); 的会话。

编辑 2:

测试代码但使用 set_time_limit(90) 增加最大执行时间根本没有帮助。它只是给出相同的错误(等待更长的时间后)并且 $_SESSION['numItems'] 以更高的值结束(大约 21000)。

【问题讨论】:

  • 你为什么经常打开和关闭会话?您应该只需要使用一次session_start()
  • 让我重新表述一下。您为什么要在该循环内编写/关闭重新打开会话。为什么不在循环后写入/关闭一次?首先准备好所有数据,然后开始/写入/关闭会话
  • 会话是 I/O。您必须打开会话文件,将数据反序列化到内存中。然后您写入会话,并将其序列化回磁盘。一遍又一遍地这样做需要一些时间,尽管 +30 秒似乎很极端。您是否使用自定义会话实现,例如远程数据库?您是否有数十万个项目需要迭代?
  • @MikeW @crush 这是因为这样在 foreach 运行时我可以从另一个文件中读取$_SESSION['numItems'],因此用户可以获得长时间执行过程的实时信息。谢谢!
  • 为什么你要做unset($_SESSION['numItems']);,如果你必须取消它而不是做$_SESSION['numItems']++;的目的

标签: php session foreach infinite-loop


【解决方案1】:

你不必一次又一次地写session_startsession_write_close

session_start();

$items=$_SESSION['items'];
$_SESSION['numItems']=0;

foreach($items as $num => $currentItem){
   $_SESSION['numItems']++;
}

unset($_SESSION['numItems']);
session_write_close();

【讨论】:

  • 代码是这样的,因为这样在 foreach 运行时我可以从另一个文件中读取 $_SESSION['numItems'] ,因此用户可以获得长时间执行过程的实时信息。谢谢!
【解决方案2】:

会话的基本用法是:http://www.php.net/manual/en/session.examples.basic.php

在第一个 session_start 之后删除所有 session_start() 和 session_write_close() 应该可以解决您的问题。

【讨论】:

  • 代码是这样的,因为这样在 foreach 运行时我可以从另一个文件中读取 $_SESSION['numItems'] ,因此用户可以获得长时间执行过程的实时信息。谢谢!
  • 那我建议你把长任务的进度存入数据库。同样对于可能超过 php 最大执行时间的任务,请考虑异步运行它们(使用 Gearman 或其他工具)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2020-10-24
  • 2018-02-03
  • 2012-02-20
  • 2015-02-04
相关资源
最近更新 更多