2016-05-17 12 views
0

私は、ユーザーがチャートを持つリストを参照する必要があるアプリケーションで作業しています。グラフのデータはデータベース(現在は約785行)から取り出され、ソートされて有効なJSON文字列になります。エラー:右私はそれが「536870912バイトの許可メモリサイズが使い果たさ(71バイトを割り当てしようとした)致命的なエラー」を与えるのコードを実行しようとすると、この大規模なJSON文字列を作成するPHP

よう
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); 

それをやろうではありません。私は最大限のメモリを増やそうとしましたが、何が起こるか見るだけですが、私は同じ結果を得ました。

これほど多くのループを実行する必要はありませんか?あるいは、私はこれと全く違うやり方からアプローチしなければならないのですか?

最終的な結果は、すべてのヘルプはいただければ幸いです。この

[{"name":"Some name", "date":["2016-05-09", "2016-05-10", "2016-05-11"], "android":["3", "1", "8"], "ios":["4", "7", "5"]},...] 

ようになるはずです!

+0

[許容されるメモリサイズは33554432バイト(43148176バイトを割り当てようとしました)](http://stackoverflow.com/questions/415801/allowed-memory-size-of-33554432-bytes-exhausted) try-to-allocate-43148176-byte) –

答えて

1

メモリの問題は "for"ループにあります。ループごとに$ appDataにアイテムの束を追加することができます。「一致する名前がない場合は1つだけ」ではなくたとえば、$ appDataに既に100個の項目があり、$ row ['name']が$ appDataの最後の項目と一致する場合、$ appDataの最後の項目が更新される前に$ appDataに99項目が追加されます。私は、現在のコードが$ appDataを785個以上の項目で生成していると確信しています。

このような何かにループ「のために」に変更、メモリの問題を修正するには:効率のノートで

$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により示唆されるように連想配列を使用すると、大きなスピードアップになります。

+0

魅力のように動作します、ありがとうございます! :) –

1

問題はループの数ではなく、$appData配列のサイズとPHP設定のmemory_limit値です。

渡すデータのサイズを縮小できない場合は、memory_limit値を大きくする必要があります。しかし、この値を増やしている間は、サーバーが実行する各実行中のPHPスクリプトの値であるため、注意してください。私は、各ループの出力バッファにページを設定するか、送信することをお勧めします。

例のコードが必要な場合は、質問してください。

ページネーションは、PHPスクリプトがそれ以上許可しなくなるまで、javascriptページがX回のPHPスクリプトを呼び出してN回ごとにN行を取得することを意味します。

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の変数内のすべてのデータを累積しないこの方法です。

+0

例がある場合は、それは素晴らしいでしょう! –

+0

私は自分の答えを更新しました。 – JesusTheHun

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)."]"; 
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']; 
} 
関連する問題