简体   繁体   中英

if else statement within foreach causes error

I have a php function used to update/add discount pricing to products in bulk.

The code worked perfectly until I added the additional $new_price conditions & substr check on the sku
I added the p.sku in the select statement. It now gives me a blank screen and the query is not run when I try to execute it.

if ($user_group == 15 && $percent == 0) {
$this->db->query("DELETE FROM " . DB_PREFIX . "product_discount WHERE customer_group_id = '".$user_group."' AND quantity = '".$quantity."'");

    $query = $this->db->query("SELECT p.product_id, p.sku, p.cost, p.price FROM product p");

    foreach ($query->rows as $result) {

        if ((substr($result['sku'],0,3) == 'ACA')) {
        $new_price = ($result['cost'] * 32.5 / 100 + $result['cost']);
        } else {
        $new_price = ($result['cost'] * 40 / 100 + $result['cost']);
        }

        $this->db->query("INSERT INTO " . DB_PREFIX . "product_discount SET 
        `product_id` = '" . $result['product_id'] . "', 
        `customer_group_id` = '15',
        `quantity` = '".$quantity."',
        `priority` = '".$priority."',
        `price` = '".$new_price."',
        `date_start` = '".$start_date."',
        `date_end` = '".$expire_date."'");
    }

}

What am I missing here? I've been searching the forum & google etc and trying various things all afternoon and i'm fed up! Please help anyone!

After adding error reporting to the index.php I finally got a clue:
"Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes)"

Here is the full code for the function with some minor changes based on the comments, I have no idea why all memory is used up hopefully someone can help:

<?php
    class ModelBulkDiscount extends Model {

    public function updateDiscount($user_group = null, $percent = 0, $quantity = 1, $priority = 0, $start_date = null, $expire_date = null) {

if($user_group != 15 && $percent > 0) {
$this->db->query("DELETE FROM " . DB_PREFIX . "product_discount WHERE customer_group_id = '".$user_group."' AND quantity = '".$quantity."'");

    $query = $this->db->query("SELECT p.product_id, p.price FROM " . DB_PREFIX . "product p");

    foreach ($query->rows as $result) {

        $new_price = $result['price'] - (($result['price'] / 100) * $percent);

        $this->db->query("INSERT INTO " . DB_PREFIX . "product_discount SET 
        `product_id` = '" . $result['product_id'] . "', 
        `customer_group_id` = '" . $user_group . "',
        `quantity` = '".$quantity."',
        `priority` = '".$priority."',
        `price` = '".$new_price."',
        `date_start` = '".$start_date."',
        `date_end` = '".$expire_date."'");

    }

} else if ($user_group == 15 && $percent == 0) {
$this->db->query("DELETE FROM " . DB_PREFIX . "product_discount WHERE customer_group_id = '".$user_group."' AND quantity = '".$quantity."'");

    $query = $this->db->query("SELECT p.product_id, p.sku, p.cost, p.price FROM " . DB_PREFIX . "product p");

    foreach ($query->rows as $result) {

    if ((substr($result['sku'],0,3) == 'ACA')) {
        $new_price = ($result['cost'] * 1.325);
    } else {
        $new_price = ($result['cost'] * 1.4);
    }

        $this->db->query("INSERT INTO " . DB_PREFIX . "product_discount SET 
        `product_id` = '" . $result['product_id'] . "', 
        `customer_group_id` = '15',
        `quantity` = '".$quantity."',
        `priority` = '".$priority."',
        `price` = '".$new_price."',
        `date_start` = '".$start_date."',
        `date_end` = '".$expire_date."'");
    }

} else if ($user_group == 15 && $percent > 0) {
$this->db->query("DELETE FROM " . DB_PREFIX . "product_discount WHERE customer_group_id = '".$user_group."' AND quantity = '".$quantity."'");

    $query = $this->db->query("SELECT p.product_id, p.cost, p.price FROM " . DB_PREFIX . "product p");

    foreach ($query->rows as $result) {
        $temp_price = ($result['cost'] * 1.325);
        $new_price = $temp_price - (($temp_price / 100) * $percent);

        $this->db->query("INSERT INTO " . DB_PREFIX . "product_discount SET 
        `product_id` = '" . $result['product_id'] . "', 
        `customer_group_id` = '15',
        `quantity` = '".$quantity."',
        `priority` = '".$priority."',
        `price` = '".$new_price."',
        `date_start` = '".$start_date."',
        `date_end` = '".$expire_date."'");
    }
}
}
}
?>

The only thing I can imagine from looking at your code might be that the initial SQL query returns a dataset which exceeds PHP's memory limits. Maybe you could try adding a LIMIT 100 or similar to the query, and see if the problem persists. You could also look for a way to get the table's size in bytes from the DB server, and see if it exceeds 128MB.

On another note: Processing a large number of records in PHP is not the best approach performance-wise, since the whole data has to be transferred from the SQL server to the PHP interpreter process and then transferred back. The code you posted looks like something you would typically implement directly in the data base with a special query (maybe even using stored procedures).

Essentially, you're trying to insert a large number of records based on data from another table. So you want to perform a select on that table and use it as a subexpression for your insert. Have a look at: https://dev.mysql.com/doc/refman/5.1/en/insert-select.html

I don't consider myself an SQL expert, but to give you an idea how this might work, just for a subset of the fields:

INSERT INTO product_discount (product_id, customer_product_id, new_price) SELECT 
sub.product_id, 15, sub.new_price FROM (
    SELECT p.product_id, p.price*1.35 AS new_price FROM products
) AS sub;

I've left out part of the new_price calculation, since it would have required another sub-SELECT, and I wanted to preserve readability. 我已经省略了new_price计算的一部分,因为它需要另一个sub-SELECT,并且我想保留可读性。 But it is also possible using pure SQL. It's not as intuitive as imperative programming, but SQL offers a lot of functionality, and stuff like conditional expressions are also possible.

You should be able to formulate a query which performs the desired operation entirely in the DB. That way, there is no need to transfer any data between DB and PHP, which will very likely be much faster, and you won't run out of memory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM