【问题标题】:Process array in chunks using PHP使用 PHP 分块处理数组
【发布时间】:2011-06-06 17:56:23
【问题描述】:

我从我的 PHP 脚本连接到并在其上执行查询的数据库中获取了大约 500 行数据。对于返回的每一行,我以表格格式显示。脚本在 Firefox 中运行良好,最终在 IE 中运行,但在一切正常显示之前,用户会收到 1 或 2 次“停止运行此脚本”提示(并告诉 IE 继续..)。

为了解决这个问题,我需要将一些数据发送回浏览器——我认为最好的方法是分块/批量处理数组。 PHP 有一个array_chunk 函数,但我无法在这里弄清楚如何使用它。

要获取数据库行,我使用:

$result = mssql_query($query);

...然后将它们显示在表格中:

while($row = mssql_fetch_array($result))
{
  [DISPLAY TABLE ROW IN TABLE]
}

使用 array_chunk 处理我的数组的最佳方式是什么,比如以 50 个为一组?

【问题讨论】:

  • 您想将它们分成几批,以便再次插入标题吗?
  • @Damp - 我想将它们分成批次,以便在处理过程中更新浏览器 - 我可以避免脚本无响应/停止运行长时间运行的脚本触发的脚本方法即。

标签: php arrays chunking


【解决方案1】:

array_chunk 只会在您从数据库中获得全部信息后才能为您提供帮助。从您的问题来看,听起来脚本挂在数据库中的实际查询上,因为它被设置为一个数组,然后您想要处理整个数组。

您可以在仍位于用于从数据库中获取每一行结果的loop 中时输出表的每一行,而不是先创建一个主数组。但是,您的用户可能会在您的脚本通过查询时看到页面加载。

现在离开您的问题主题:如果分块加载的页面对您来说不太理想,您可以考虑在后台异步运行查询(使用 JavaScript),同时显示某种“正在加载”消息,直到脚本运行完毕。然后,将结果输出到页面。

或者,如果您可以选择不一次显示所有 500 多个结果,则可以使用分页并使用 LIMITOFFSET SQL 关键字来仅获取整个查询的一部分。然后,创建指向将更改 OFFSET 的结果的下一页或上一页的链接。

【讨论】:

  • @ mririgo -- 感谢您的回复。我需要在表格中显示所有结果——因为在那之后,我使用了一个链接到表格上方的文本字段的插件,该插件将允许用户根据文本字段输入过滤(显示/隐藏)特定的表格行.如果该字段为空白,我想显示所有行。我试过jquery AJAX请求,但是IE浏览器在等待时仍然显示错误...
  • 我将结合使用递归 AJAX 调用来查询数据库中有限数量的行,直到返回所有行。仅供参考: LIMIT 不能在 SQL SERVER 上使用!必须为此使用自定义解决方案。
【解决方案2】:

您一次向浏览器发送了一堆数据。为了使其表现良好,可以:

  1. 发送更少的数据。 正如其他答案所建议的那样,使用 SQL LIMIT 对结果进行分页,并输出链接以在页面中来回导航(/data/page/1、@987654323 @、/data/page/last 等)。这有一个次要影响:您的 PHP 和 SQL 将执行得更快,因为您在服务器上处理的每个请求的数据更少。

  2. 以更小的块发送数据。在循环遍历行时,定期调用flush();(每行$n),让浏览器有时间在获取之前显示一些结果更多。

  3. 以增量方式提取数据。您还可以通过 AJAX 以较小的位(例如一次 50 行)获取结果。您可以将其放在上述或类似的分页顶部。

  4. 使数据更小。 最小化返回给浏览器的 HTML 的大小也会产生显着的差异。您可以删除额外的<div> 标签、类、ID 或缩写内容本身(链接回完整的详细信息)。您还可以以更简洁的格式(如 JSON)发送数据,并使用 JavaScript 对其进行扩展。

【讨论】:

  • 谢谢,布鲁斯。我对#2 和#3 感兴趣。在上面的代码示例中,我将如何使用flush?如果我选择选项 3,我不确定如何为返回的 500 行中的 50 行发出 ajax 请求..
  • 对于flush();,以$n 的间隔添加到您的while 循环(if ($row % 50 == 0) flush();)。至于 AJAX,您需要像 #1 一样进行分页,并使用 SQL LIMIT $n, $o 返回查询的子集。
【解决方案3】:

你问错了问题,我认为...... array_chunk 不是你最好的选择,因为你需要完整的数组来分块它。 Ergo: 你应该已经遍历了整个结果集一次。

为什么不直接在你那里的while循环中输出?

如果您觉得必须对数据进行分块,请使用外部计数器。在循环内递增,并使用 MODULO 操作数检查该值。

$i = 0;
while($row = mssql_fetch_array($result))
{
  if(++$i % 500 == 0) {
    [DISPLAY TABLE ROW IN TABLE]
  }
}

【讨论】:

    猜你喜欢
    • 2018-11-02
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多