You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrestaShop模块displayProductPriceBlock钩子重复触发问题

PrestaShop模块钩子重复触发导致价格多次折扣问题修复

问题描述

开发了名为HalvePriceOutOfStock的PrestaShop模块,通过displayProductPriceBlock钩子为缺货商品价格减2。测试发现钩子被触发两次,原本22元的商品价格变成16元(被连续减了两次2)。尝试用全局标记变量控制执行次数,却导致其他商品无法正常触发钩子。

问题根源

  1. displayProductPriceBlock钩子在PrestaShop中可能被多次调用(例如商品列表、商品详情页的不同价格区块,或原价/折扣价的渲染场景)
  2. 直接修改$params['product']['price']会导致后续钩子调用基于已修改的价格重复计算
  3. 通过解析格式化后的价格字符串来计算折扣,容易出现格式兼容问题,且依赖不稳定的字符串处理

修复方案

核心思路

  • 限制钩子仅在主价格区块触发,跳过无关价格场景
  • 按商品ID标记处理状态,确保每个商品只被修改一次
  • 直接调用PrestaShop原生API获取原始价格,替代字符串解析逻辑

修改后的完整代码

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}

class HalvePriceOutOfStock extends Module
{
    public function __construct()
    {
        $this->name = 'halvepriceoutofstock';
        $this->tab = 'pricing_promotion';
        $this->version = '0.1.0';
        $this->author = 'Ali Fertah';
        $this->need_instance = 0;

        parent::__construct();

        $this->displayName = $this->l('Halve Price for Out-of-Stock Products');
        $this->description = $this->l('Displays out-of-stock products with half the original price.');

        $this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_);
    }

    public function install()
    {
        return parent::install() && $this->registerHook('displayProductPriceBlock');
    }

    public function uninstall()
    {
        return parent::uninstall();
    }

    public function hookDisplayProductPriceBlock($params)
    {
        // 仅处理主价格区块,跳过原价、促销价等其他价格渲染场景
        if ($params['type'] !== 'price') {
            return;
        }

        $productId = $params['product']['id_product'];
        // 按商品ID标记已处理状态,避免同个商品被重复折扣
        if (!isset($this->context->processed_products[$productId])) {
            $params['product']['price'] = $this->updateProductPrice($productId);
            $this->context->processed_products[$productId] = true;
        }

        $this->context->smarty->assign(array(
            'product_price' => $params['product']['price']
        ));
    }

    public function updateProductPrice($productId)
    {
        $product = new Product($productId);
        if ($product->quantity <= 0) {
            // 获取商品原始含税价格(改为getPrice(false, ...)可获取不含税价格)
            $originalPrice = (float)$product->getPrice(true, null, 6);
            $discountedPrice = $originalPrice - 2;
            // 用PrestaShop原生工具格式化价格,适配当前货币和本地化设置
            return $this->context->currency->format($discountedPrice, $this->context->currency->id, false);
        } else {
            // 返回商品原价格
            return $this->context->currency->format($product->getPrice(true, null, 6), $this->context->currency->id, false);
        }
    }
}

关键修改说明

  • 增加type参数判断,过滤掉非主价格的钩子调用
  • 基于商品ID的状态标记,确保每个商品仅被折扣一次
  • 直接通过Product对象获取原始价格,避免字符串解析的兼容性问题
  • 使用PrestaShop原生价格格式化方法,适配不同货币和地区的格式要求

内容的提问来源于stack exchange,提问作者scofio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:23:13