Gibt es eine effizientere Möglichkeit, Abfragen innerhalb einer Schleife zu laufen? Speicherprobleme

StackOverflow https://stackoverflow.com/questions/3856555

Frage

Ich habe eine Joomla Website, dass ich für eine benutzerdefinierte Warenkorb Komponente geschrieben haben. Der Nutzer kauft grundsätzlich Codes in unserer Datenbank erfasst sind speichern - diese sind mit einer gedruckten Anreiz Karte zugeordnet. Wenn der Benutzer checkt, muss ich aus der Datenbank ein Stück Codes greifen (wie viele sie gekauft haben), dann die Schleife durch die Liste der Codes und aktualisieren andere Tabellen mit Informationen in den Warenkorb. Der Wagen als ein Array von Arrays in einer Sitzungsvariablen gespeichert ist, wie folgt aus:

$cart = Array ( 
[0] => Array ( [TypeFlag] => S [qty] => 25 [denom] => 50  [totalPrice] =>  100 )
[1] => Array ( [TypeFlag] => V [qty] => 10 [denom] => 25  [totalPrice] => 25 ) 
[2] => Array ( [TypeFlag] => C [qty] => 100 [denom] => 25  [totalPrice] => 25 ) 
) 

, wobei jedes interne Array eine Zeile Artikel in den Warenkorb gelegt ist. Es ist die Menge, die das Problem verursacht; wenn sie niedrig, es gibt kein Problem, alle der Einsatz und Aktualisierungsabfragen innerhalb der Schleife ausgeführt wird. Wenn jedoch die Menge Elemente hoch sind, fange ich an Speicherzuordnungsfehler bekommen. Dies ist verständlich, da es im Grunde hat mehrere Abfragen hunderte Male ausgeführt wird. Das Problem ist, könnte ein Benutzer möglicherweise bestellt tausend oder mehr Karten zu einem Zeitpunkt (dies ist ein Firmen-Incentive-Programm), so dass ich alle Datensätze erhalten muß in die Lage eingefügt und aktualisiert werden, unabhängig davon, wie groß die Menge ist.

Hier ist der relevante Code:

Zuerst wird die Schleife:

//loop through vouchers to create purchase records, update voucher records, create certificates
$rightNow = date("YmdHis");
foreach($vouchers as $voucher) {
    $VoucherID = $voucher['VoucherID'];
    $VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];
    //create purchase record            
    $purchData = array("CcAuthCode"=>$ccAuthCode,"VoucherID"=>$VoucherID,"PurchAmt"=>$realFinalTotal, "ShipHandFee"=>number_format($shippingCharge,2),  "PurchDT"=>$rightNow,  "AcctID"=>$accountIDs['UserAcctID'], "ShipAddrID"=>$accountIDs['MailingAcctID']);
    $purchID = $model->createPurchaseRecord($purchData);    

    //update voucher
    $model->updateVoucherInfo($VoucherID,$accountIDs['BillingAcctID'], $denom, $purchID,$message);
}

Die tatsächlichen Abfragen sind in der createPurchaseRecord und updateVoucherInfo Funktionen im Modell:

function createPurchaseRecord($data){    
    $db =& JFactory::getDBO();
    $insFields = "";
    $valFields = "";

    foreach ($data as $f => $v){
        $insFields .= "," . $f;
        $valFields .= "," . $db->quote($v);
    }

    $insFields = substr($insFields,1);
    $valFields = substr($valFields,1);

    $query = "insert into arrc_PurchaseActivity ({$insFields}) values ({$valFields})";
    $db->setQuery($query);
    if (!$db->query()) error_log($db->stderr());

    return $db->insertid();
}

function updateVoucherInfo($voucherID,$billingAcctId, $balanceInit, $purchID, $certMessage) {
    //set ActivatedDT, BalanceInit
    $rightNow = date("YmdHis");
    $db =& JFactory::getDBO();
    $query = "UPDATE arrc_Voucher 
        set ActivatedDT=".$db->quote($rightNow).", BalanceInit=".$db->quote($balanceInit) . ", BalanceCurrent=".$db->quote($balanceInit).
    ", AcctID=".$db->quote($billingAcctId).", PurchActvtyID=".$db->quote($purchID) . ", certMessage=".$db->quote($certMessage)
    . " WHERE VoucherID=".$db->quote($voucherID);

    $db->setQuery($query);
    if (!$db->query()) error_log($db->stderr()); 
    $certificateNumber = $voucherID;
    return $certificateNumber;

}

Kann mir jemand helfen aus? Es muss ein Weg, um diesen effizienter zu gestalten; Im Moment ist es einen Speicherfehler zu werfen, wenn ich versuche, mehr als 30 oder so zu einer Zeit zu tun; die Forderung nach mehr als 1.000 gegeben, das ist eine große Sache. Dies ist der Fehler:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71303153 bytes) in /var/www/html/mysite.com/components/com_arrcard/controllers/checkout.php on line 110

Line 110 ist diese Linie von der Schleife über:

   $VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];
War es hilfreich?

Lösung

$VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];

Sie tun dies falsch. Sie verketten die Liste selbst in den Variablen resultierenden wachsen exponentiell.

Die richtige Art und Weise:

$VoucherIDList .= "," . $voucher['VoucherNbr'];

oder

$VoucherIDList = $VoucherIDList ."," . $voucher['VoucherNbr'];

Viele Grüße, Alin

Andere Tipps

Um Ihren Code zu wenig sauberer zu machen und unnötige Anrufe beseitigen.

Anstelle von

foreach ($data as $f => $v){
    $insFields .= "," . $f;
    $valFields .= "," . $db->quote($v);
}

Mit

$valFields = implode(',', $data);
$insFields = implode(',', array_keys($data));

Erhöhung der Speichernutzung in php.ini

Wenn Sie mit PHP 5, lose &.

Statt durch Array von Arrays von looping. Last $vouchers als Array von Objekten, Objekte als Referenz übergeben werden, anstatt nach Wert.

foreach($vouchers as $voucher) {

$VoucherIDList .= $VoucherIDList ."," . $voucher['VoucherNbr'];

Mit dem. Operator = Sie eine Verkettung von $VoucherIDList an sich selbst tun.

Mit der Anweisung oben, Sie dann auch wieder $VoucherIDList zur Liste hinzuzufügen.

Wie Alin oben gesagt, den Sie hinzufügen, um die Variable selbst jedes Mal, exponentiell die Schleife ausgeführt wird.

Ich würde dies erraten ist, warum Sie die Fehler Probleme bekommen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top