Apache 在 PHP 关联数组的大型 foreach 循环中崩溃

发布于 2024-11-02 12:00:27 字数 2746 浏览 0 评论 0原文

编辑:为了响应 Robus 的回答,我尝试从命令行运行 PHP 脚本。这是结果:

CLI crash

但有趣的是;位于我的代码中的 foreach 循环之后的 echo 语句将其文本输出到控制台窗口。因此我只能假设 CLI 在运行脚本后 / 结束时崩溃。


我有一个脚本,其功能是将 XLSX 文件中的所有行加载到 MySQL 表中。我为此使用 PHPExcel。我编写了函数 loadFromXLS 来从 XLSX 文件加载数据并返回包含数据的二维数组。在本例中,这意味着 3100 行和 29 列。

这是功能:

function loadFromXLS($filepath)
{
    $retval = array();
    $cols = array();
    $rownum = 0;

    $reader = PHPExcel_IOFactory::createReaderForFile($filepath);
    $reader->setReadDataOnly(true);

    $phpObject = $reader->load($filepath);
    $sheet = $phpObject->getActiveSheet();

    foreach($sheet->getRowIterator() as $row)
    {
        $celliterator = $row->getCellIterator();
        $celliterator->setIterateOnlyExistingCells(false);
        $cellnum = 0;

        foreach($celliterator as $cell)
        {
            if($rownum === 0)
            {
                $cols[$cellnum] = $cell->getValue();
            }
            else
            {
                if(is_array($retval[$rownum-1]))
                    $retval[$rownum-1] += array($cols[$cellnum] => $cell->getValue());
                else
                    $retval[$rownum-1] = array($cols[$cellnum] => $cell->getValue());
            }

            $cellnum++;
        }

        $rownum++;
    }

    unset($reader, $phpObject, $sheet);

    return $retval;
}

文件的顶行是列名称。

无论如何,我已经通过 var_dump 处理前几行并检查数组长度来确认它正确加载数据。

这就是问题所在。一旦我添加这一行:

foreach($data as $i => $row) {};

Apache 在到达该点时就会崩溃:

Apache crash

那这是怎么回事? PHP 不能处理大型关联数组的循环吗?任何解释性答案将不胜感激。如果我可以提供其他信息,请发表评论


我在 Windows 7、Intel i5 处理器、4GB RAM 上运行 XAMPP。我已将 php.ini 中的 memory_limit 增加到 512MB,这已经足够了(当它设置为 128MB 时,它曾经给我带来内存错误)。该脚本包括 PHPExcel.php 和 dBug.php。二维数组仅填充字符串,没有时髦的 PHPExcel 数据类型。

我正在运行 PHP 版本 5.3.1

加载的模块: core mod_win32 mpm_winnt http_core mod_so mod_actions mod_alias mod_asis mod_auth_basic mod_auth_digest mod_authn_default mod_authn_file mod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_cgi mod_dav mod_dav_fs mod_dav_lock mod_dir mod_env mod_headers mod_include mod_info mod_isapi mod_log_config mod_mime mod_negotiation mod_rewrite mod_setenvif mod_ssl mod_status mod_autoindex_color mod_php5 mod_perl mod_apreq2

phpinfo() 截图

EDIT: In response to Robus' answer I tried to run the PHP script from command line. This is the result:

CLI crash

But interestingly; an echo statement that was located after the foreach loop in my code output it's text to the console window. Thus I can only assume that CLI crashes at the conclusion of / after running the script.


I have a script which function is to load all rows from an XLSX file into a MySQL table. I am using PHPExcel for this. I wrote the function loadFromXLS to load the data from the XLSX file and return a two dimensional array with the data. In this particular case that means 3100 rows and 29 columns.

This is the function:

function loadFromXLS($filepath)
{
    $retval = array();
    $cols = array();
    $rownum = 0;

    $reader = PHPExcel_IOFactory::createReaderForFile($filepath);
    $reader->setReadDataOnly(true);

    $phpObject = $reader->load($filepath);
    $sheet = $phpObject->getActiveSheet();

    foreach($sheet->getRowIterator() as $row)
    {
        $celliterator = $row->getCellIterator();
        $celliterator->setIterateOnlyExistingCells(false);
        $cellnum = 0;

        foreach($celliterator as $cell)
        {
            if($rownum === 0)
            {
                $cols[$cellnum] = $cell->getValue();
            }
            else
            {
                if(is_array($retval[$rownum-1]))
                    $retval[$rownum-1] += array($cols[$cellnum] => $cell->getValue());
                else
                    $retval[$rownum-1] = array($cols[$cellnum] => $cell->getValue());
            }

            $cellnum++;
        }

        $rownum++;
    }

    unset($reader, $phpObject, $sheet);

    return $retval;
}

The top row of the file is the column names.

In any case, I have confirmed that it loads the data correctly by var_dumping the first few rows and checking the array length.

This is the problem. As soon as I add this line:

foreach($data as $i => $row) {};

Apache simply crashes when it gets to that point:

Apache crash

So what's up with that? Can't PHP handle loops through large associative arrays? Any explanatory answers would be appreciated. Please comment if there is additional information I can provide


I'm running XAMPP on Windows 7, Intel i5 processor, 4GB RAM. I have increased memory_limit in php.ini to 512MB which is more than enough (It used to give me a memory error when it was set to 128MB). This script includes PHPExcel.php and dBug.php. The two dimensional array is only filled with strings, no funky PHPExcel datatypes.

I'm running PHP version 5.3.1

Loaded modules: core mod_win32 mpm_winnt http_core mod_so mod_actions mod_alias mod_asis mod_auth_basic mod_auth_digest mod_authn_default mod_authn_file mod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_cgi mod_dav mod_dav_fs mod_dav_lock mod_dir mod_env mod_headers mod_include mod_info mod_isapi mod_log_config mod_mime mod_negotiation mod_rewrite mod_setenvif mod_ssl mod_status mod_autoindex_color mod_php5 mod_perl mod_apreq2

phpinfo() screenshot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

木緿 2024-11-09 12:00:27

尝试完全省略 apache,只从命令行运行脚本,看看会发生什么

Try omitting apache altogether and just run the script from command line, see what happens

Saygoodbye 2024-11-09 12:00:27

更新你的 php 安装..

Update your php installation..

倾城泪 2024-11-09 12:00:27
  1. 为 PHP 添加一些内存。

  2. 在 PHP 中返回一个大数组不太幸运。您应该使用:

    function loadFromXLS($filepath,&$retval) {
      ...
    }
    

    那么你应该删除$retval = array();并将其放在该函数的调用之前。

  1. Add some memory to PHP.

  2. It's not too lucky to return a big array in PHP. You should use instead:

    function loadFromXLS($filepath,&$retval) {
      ...
    }
    

    Then you should remove $retval = array(); and put it before the call of this funct.

笑饮青盏花 2024-11-09 12:00:27

简单地取消设置 $phpObject 和 $sheet 将不会产生任何效果。它们包含循环对象引用,在 PHP 中不能很好地清理,因此除非您首先破坏这些引用,否则它们不会被取消设置。这可以

$phpObject->disconnectWorksheets();

按照开发人员文档第 4.3 节(“从内存中清除工作簿”)中的描述来完成。

摆脱迭代器循环来填充数组,并使用 PHPExcel 的内置方法。

return $sheet->toArray(); 

您还可以将以下参数传递给 toArray() 方法:

* @param  mixed    $nullValue            Value returned in the array entry if a cell doesn't exist
* @param  boolean  $calculateFormulas    Should formulas be calculated?
* @param  boolean  $formatData           Should formatting be applied to cell values?
* @param  boolean  $returnCellRef        False - Return a simple array of rows and columns indexed by number counting from zero
*                                        True - Return rows and columns indexed by their actual row and column IDs

它不会为您提供您自己的循环所提供的关联数组,但它会比您的循环更快、内存效率更高。

Simply unsetting $phpObject and $sheet will have no effect whatsoever. These contain cyclic object references, which don't clean-up well in PHP, so they will not be unset unless you break those references first. This can be done using

$phpObject->disconnectWorksheets();

as described in section 4.3 of the developer documentation ("Clearing a Workbook from memory").

Get rid of the iterator loops to populate your array, and use PHPExcel's built-in method.

return $sheet->toArray(); 

You can also pass the following arguments to the toArray() method:

* @param  mixed    $nullValue            Value returned in the array entry if a cell doesn't exist
* @param  boolean  $calculateFormulas    Should formulas be calculated?
* @param  boolean  $formatData           Should formatting be applied to cell values?
* @param  boolean  $returnCellRef        False - Return a simple array of rows and columns indexed by number counting from zero
*                                        True - Return rows and columns indexed by their actual row and column IDs

It won't give you quite the associative array that your own loops do, but it will be faster, and more memory efficient that your loops.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文