我正在开发一个应用程序,用户应该看到一个包含图表的列表。应该从数据库(当前大约785行)中获取图表的数据,然后对其进行排序以形成有效的JSON字符串。对不,我试着像这样做
staging
当我尝试运行代码时,它会给出一个"致命错误:允许的内存大小为536870912字节耗尽(试图分配71个字节)"错误。我试图增加最大允许内存,只是为了看看会发生什么,但我得到了相同的结果。
有没有办法避免必须这么多循环?或者我应该从一个完全不同的方式来解决这个问题,如果是这样的话?
最终结果看起来应该是这样的
while($row = $res->fetch_assoc()) {
if(count($appData) == 0 ){
$appData[] = array(
"name" => $row["name"],
"date" => array($row["date"]),
"android" => array($row["android_count"]),
"ios" => array($row["apple_count"])
);
}else {
for($i = 0; $i < count($appData); $i++) {
if($appData[$i]["name"] == $row["name"]){
$appData[$i]["date"][] = $row["date"];
$appData[$i]["android"][] = $row["android_count"];
$appData[$i]["ios"][] = $row["apple_count"];
}else {
$appData[] = array(
"name" => $row["name"],
"date" => array($row["date"]),
"android" => array($row["android_count"]),
"ios" => array($row["apple_count"])
);
}
}
}
}
echo json_encode($appData);
所有帮助将不胜感激!
答案 0 :(得分:1)
您的问题不是循环次数,而是$appData
数组的大小和php配置的memory_limit值。
如果无法缩小传递的数据大小,则必须增加memory_limit值。但是在增加此值时要小心,因为它是服务器将执行的每个运行的php脚本的值。我建议在每个循环中分页或发送到输出缓冲区。
如果您需要代码示例,请提出要求。
分页意味着您的javascript页面将调用X次PHP脚本以每次检索N行,直到PHP脚本不再允许它为止。因此,您必须返回一个数组,如:
return array(
'nextPage' => 2, // More data available on this page
'data' => $json
);
// Or
return array(
'nextPage' => null, // No more data available
'data' => $json
);
或者在每个循环上发送到输出缓冲区并释放内存:
$first = true;
echo '[';
while($row = $res->fetch_assoc()) {
if(!$first) {
echo ',';
} else {
$first = false;
}
// some logic
$row_data = array(...);
echo json_encode($row_data);
}
echo ']';
这样你就不会在php的变量中堆叠所有数据。
答案 1 :(得分:1)
内存问题出在&#34; for&#34;环。它可以为每个循环的$ appData添加一堆项目,而不是&#34;如果没有匹配的名称,只需添加一个。&#34;例如,如果$ appData中已有100个项目,并且$ row [&#39; name&#39;]匹配$ appData中的最后一项,那么$ appData中的最后一项之前将有99个项目添加到$ appData已更新。我敢打赌,当前代码生成的$ appData包含超过785项。
要解决内存问题,请更改&#34; for&#34;循环到这样的事情:
$matchFound = false;
for($i = 0; $i < count($appData); $i++) {
if($appData[$i]["name"] == $row["name"]){
$appData[$i]["date"][] = $row["date"];
$appData[$i]["android"][] = $row["android_count"];
$appData[$i]["ios"][] = $row["apple_count"];
$matchFound = true;
break;
}
}
if (!$matchFound) {
$appData[] = array(
"name" => $row["name"],
"date" => array($row["date"]),
"android" => array($row["android_count"]),
"ios" => array($row["apple_count"])
);
}
在效率上,使用maximkou建议的关联数组将是一个很大的加速。
答案 2 :(得分:0)
按$row['name']
索引数组。这有助于简化您的代码。 php中的数组分配了许多内存,因此按行编码嵌套数据。如果您知道结果数组大小,请尝试使用SplFixedArray。
试试这个:
while($row = $res->fetch_assoc()) {
$appData[ $row["name"] ] = json_encode(array(
"name" => $row["name"],
"date" => array($row["date"]),
"android" => array($row["android_count"]),
"ios" => array($row["apple_count"])
));
}
echo "[".implode(',', $appData)."]";
答案 3 :(得分:0)
这应该创建完全相同的结果(尚未测试),并使用地图数组和array_key_exists()
来避免额外的循环。这可以在一个循环中完成。
$nameMap = array(); // hold name and keys
while($row = $res->fetch_assoc()){
$key = array_key_exists($row['name'], $nameMap) ? $nameMap[$row['name']] : count($appData);
$nameMap[$row['name']] = $key;
if(empty($appData[$key]))
$appData[$key] = array("name"=>$row['name'], "date"=>array(), "android"=>array(), "ios"=>array());
$appData[$key]['date'][] = $row['date'];
$appData[$key]['android'][] = $row['android'];
$appData[$key]['ios'][] = $row['ios'];
}