Apache 在 PHP 关联数组的大型 foreach 循环中崩溃
编辑:为了响应 Robus 的回答,我尝试从命令行运行 PHP 脚本。这是结果:
但有趣的是;位于我的代码中的 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 在到达该点时就会崩溃:
那这是怎么回事? 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
EDIT: In response to Robus' answer I tried to run the PHP script from command line. This is the result:
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_dump
ing 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:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试完全省略 apache,只从命令行运行脚本,看看会发生什么
Try omitting apache altogether and just run the script from command line, see what happens
更新你的 php 安装..
Update your php installation..
为 PHP 添加一些内存。
在 PHP 中返回一个大数组不太幸运。您应该使用:
那么你应该删除$retval = array();并将其放在该函数的调用之前。
Add some memory to PHP.
It's not too lucky to return a big array in PHP. You should use instead:
Then you should remove $retval = array(); and put it before the call of this funct.
简单地取消设置 $phpObject 和 $sheet 将不会产生任何效果。它们包含循环对象引用,在 PHP 中不能很好地清理,因此除非您首先破坏这些引用,否则它们不会被取消设置。这可以
按照开发人员文档第 4.3 节(“从内存中清除工作簿”)中的描述来完成。
摆脱迭代器循环来填充数组,并使用 PHPExcel 的内置方法。
您还可以将以下参数传递给 toArray() 方法:
它不会为您提供您自己的循环所提供的关联数组,但它会比您的循环更快、内存效率更高。
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
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.
You can also pass the following arguments to the toArray() method:
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.