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

Prestashop模块开发:勾选复选框时添加额外金额至购物车

嘿,我刚好做过类似的Prestashop模块,给你梳理一下解决思路和具体代码,帮你搞定这个额外费用的问题!

解决Prestashop商品页自定义额外费用的问题

你之前用hookActionCartSave没成功,大概率是没找对钩子的使用时机,或者没正确存储用户的勾选状态,再或者没掌握添加自定义费用的正确方式。我给你拆解成前端交互、后台存储、费用计算、购物车显示这几个环节来解决:

1. 前端:商品页添加复选框和输入框

先在商品页的加购按钮附近添加你的复选框和输入框,用hookDisplayProductButtons钩子来渲染:

模块里注册必要钩子

public function install()
{
    return parent::install() &&
        $this->registerHook('displayProductButtons') &&
        $this->registerHook('actionCartProductAddAfter') &&
        $this->registerHook('actionCartUpdateQuantityAfter') &&
        $this->registerHook('actionCalculateAdditionalPrice') &&
        $this->registerHook('displayShoppingCart');
}

实现hookDisplayProductButtons钩子

public function hookDisplayProductButtons($params)
{
    $product = $params['product'];
    // 从购物车自定义数据中恢复之前的勾选状态
    $customization = $this->context->cart->getCustomization($product->id, true);
    $this->context->smarty->assign([
        'enable_extra_fee' => !empty($customization['enable_extra']),
        'extra_input_value' => $customization['extra_input'] ?? ''
    ]);
    return $this->display(__FILE__, 'views/templates/hook/product-buttons.tpl');
}

对应模板文件(product-buttons.tpl)

<div class="extra-service-section">
    <label class="checkbox-label">
        <input type="checkbox" name="enable_extra_fee" id="enable_extra_fee" {if $enable_extra_fee}checked{/if}>
        额外专属服务 (+{50|displayPrice})
    </label>
    <div class="extra-input-container" style="display: {if $enable_extra_fee}block{else}none{/if}; margin-top: 10px;">
        <input type="text" name="extra_input" placeholder="请填写服务需求" value="{$extra_input_value}" class="form-control">
    </div>
</div>

<script>
// 勾选/取消时切换输入框显示状态
document.getElementById('enable_extra_fee').addEventListener('change', function() {
    const inputContainer = document.querySelector('.extra-input-container');
    inputContainer.style.display = this.checked ? 'block' : 'none';
});
</script>

2. 后台:存储用户的勾选状态

当用户点击加购按钮,或者在购物车修改商品数量时,把勾选状态和输入内容存到购物车的自定义数据里:

处理商品加购后的状态存储

public function hookActionCartProductAddAfter($params)
{
    $this->saveExtraServiceStatus($params['cart'], $params['id_product']);
}

// 处理购物车商品数量修改后的状态同步
public function hookActionCartUpdateQuantityAfter($params)
{
    $this->saveExtraServiceStatus($params['cart'], $params['id_product']);
}

// 封装重复逻辑
private function saveExtraServiceStatus(Cart $cart, int $productId)
{
    $enableExtra = Tools::getValue('enable_extra_fee');
    $extraInput = Tools::getValue('extra_input');

    if ($enableExtra) {
        // 保存自定义数据到购物车
        $cart->updateCustomization(
            $productId,
            [
                'enable_extra' => 1,
                'extra_input' => $extraInput
            ],
            true
        );
    } else {
        // 移除该商品的自定义数据
        $cart->removeCustomization($productId);
    }
    $cart->save();
}

3. 核心:添加额外费用到购物车

要实现类似运费的独立费用项,推荐用Prestashop的CartExtraCost类(对应数据库表ps_cart_extra_cost),在hookActionCalculateAdditionalPrice钩子中计算并添加:

public function hookActionCalculateAdditionalPrice($params)
{
    $cart = $params['cart'];
    $totalExtraFee = 0;
    $feeLabel = $this->l('额外专属服务费用');

    // 遍历购物车所有商品,统计需要加费的项
    foreach ($cart->getProducts() as $product) {
        $customization = $cart->getCustomization($product['id_product'], true);
        if (!empty($customization['enable_extra'])) {
            $totalExtraFee += 50;
        }
    }

    // 先清除之前添加的同类费用,避免重复计算
    Db::getInstance()->delete(
        'cart_extra_cost',
        'id_cart = '.(int)$cart->id.' AND name = "'.pSQL($feeLabel).'"'
    );

    // 如果有费用,添加到购物车并更新总金额
    if ($totalExtraFee > 0) {
        $extraCost = new CartExtraCost();
        $extraCost->id_cart = $cart->id;
        $extraCost->name = $feeLabel;
        $extraCost->value = $totalExtraFee;
        $extraCost->tax_rate = 0; // 根据你的税率需求调整
        $extraCost->save();

        // 同步更新购物车总金额
        $cart->update([
            'total' => $cart->total + $totalExtraFee,
            'total_with_tax' => $cart->total_with_tax + $totalExtraFee
        ]);
    }
}

4. 购物车页面显示费用项

最后,在购物车页面显示这个独立的费用行,用hookDisplayShoppingCart钩子:

public function hookDisplayShoppingCart($params)
{
    $cart = $params['cart'];
    $totalExtraFee = 0;
    foreach ($cart->getProducts() as $product) {
        $customization = $cart->getCustomization($product['id_product'], true);
        if (!empty($customization['enable_extra'])) {
            $totalExtraFee += 50;
        }
    }
    if ($totalExtraFee > 0) {
        $this->context->smarty->assign([
            'extra_fee_label' => $this->l('额外专属服务费用'),
            'extra_fee_amount' => $totalExtraFee
        ]);
        return $this->display(__FILE__, 'views/templates/hook/shopping-cart-fee.tpl');
    }
    return '';
}

购物车费用模板(shopping-cart-fee.tpl)

<tr class="cart-extra-fee">
    <td colspan="4" class="text-right font-weight-bold">{$extra_fee_label}</td>
    <td class="text-right font-weight-bold">{$extra_fee_amount|displayPrice}</td>
</tr>

额外注意点

  • 如果你需要支持多语言,记得把费用标签用$this->l()包裹,在模块的语言文件中添加对应翻译。
  • 订单确认时,CartExtraCost会自动关联到订单,所以订单详情里也会显示这个费用项,不用额外处理。
  • 测试时要清空浏览器缓存和Prestashop的缓存,避免钩子不生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:33:53