The other performance problem is in function zen_get_products_special_price . You can find this function in the same file as above (includes/functions/functions_prices.php).
If I change the function to this;
function zen_get_products_special_price($product_id, $specials_price_only = false)
{
global $db;
// Fetch only needed fields
$sql = "SELECT products_model, master_categories_id, products_priced_by_attribute
FROM " . TABLE_PRODUCTS . "
WHERE products_id = :products_id";
$sql = $db->bindVars($sql, ':products_id', (int)$product_id, 'integer');
$product = $db->Execute($sql);
if ($product->EOF || Customer::isWholesaleCustomer() === true) {
return false;
}
$product_price = zen_get_products_base_price($product_id);
$sql = "SELECT specials_new_products_price
FROM " . TABLE_SPECIALS . "
WHERE products_id = :products_id AND status = 1";
$sql = $db->bindVars($sql, ':products_id', (int)$product_id, 'integer');
$specials = $db->Execute($sql); // Fixed: Removed incorrect parameters
if (!$specials->EOF) {
$special_price = $specials->fields['specials_new_products_price'];
} else {
$special_price = false;
}
if (strpos(($product->fields['products_model'] ?? ''), 'GIFT') === 0) {
if (!empty($special_price)) {
return $special_price;
}
return false;
}
if ($specials_price_only == true) {
if (!empty($special_price)) {
return $special_price;
}
return false;
}
$category = $product->fields['master_categories_id'];
$sale = zen_get_sale_for_category_and_price($category, $product_price);
global $zco_notifier;
$zco_notifier->notify('NOTIFY_ZEN_GET_PRODUCTS_SPECIAL_PRICE', $product->fields, $sale, $product_price);
if ($sale === false) {
return $special_price;
}
if (!$special_price) {
$tmp_special_price = $product_price;
} else {
$tmp_special_price = $special_price;
}
switch ($sale['sale_deduction_type']) {
case 0:
$sale_product_price = $product_price - $sale['sale_deduction_value'];
$sale_special_price = $tmp_special_price - $sale['sale_deduction_value'];
break;
case 1:
$sale_product_price = $product_price - (($product_price * $sale['sale_deduction_value']) / 100);
$sale_special_price = $tmp_special_price - (($tmp_special_price * $sale['sale_deduction_value']) / 100);
break;
case 2:
$sale_product_price = $sale['sale_deduction_value'];
$sale_special_price = $sale['sale_deduction_value'];
break;
default:
return $special_price;
}
if ($sale_product_price < 0) {
$sale_product_price = 0;
}
if ($sale_special_price < 0) {
$sale_special_price = 0;
}
if (!$special_price) {
return number_format($sale_product_price, 4, '.', '');
}
switch ($sale['sale_specials_condition']) {
case 0:
return number_format($sale_product_price, 4, '.', '');
break;
case 1:
return number_format($special_price, 4, '.', '');
break;
case 2:
return number_format($sale_special_price, 4, '.', '');
break;
default:
return number_format($special_price, 4, '.', '');
}
}
I'm back on 1.5.7 performance levels. And if I dig through and compare code its also logical. 1.5.7 used direct database queries in the functions. 2.1.0 uses a complete class to load -all- Product details from various database tables. This is like using a cannon to kill a fly for these two particular functions. It's way too much overhead.
Either ZenCart >2.1.0 needs to improve on this or the maintainer (lat9) of this plugin need to write these two functions into GPSF and not rely on zen_get_products_base_price/zen_get_products_special_price anymore. The difference in performance is huge.