PrestaShop模块hookActionPaymentConfirmation数据库连接及更新问题排查
PrestaShop模块hookActionPaymentConfirmation数据库操作故障排查
先看你代码里的几个致命问题,直接导致代码跑不起来:
核心错误点
- 未定义变量$campoid:你在SQL语句里直接用了
$campoid,但代码里完全没给这个变量赋值,执行到这里直接报错终止,这是最关键的问题。 - 数据库连接无错误检查:实例化
DbMySQLi后,没有判断连接是否成功,根本不知道是连不上库还是后续逻辑错了。 - getValue方法误用:
getValue是用来获取单值结果的,你用它执行select *,只会返回第一列的第一个值,根本拿不到整行数据,$rec["reference"]必然报错。 - SQL拼接存在注入风险+语法错误隐患:直接把变量拼进SQL,遇到带引号、特殊字符的
$referencia会直接导致SQL语法错误,同时有注入风险。 - Order实例化未做有效性校验:如果
$params['id_order']无效,new Order()会返回false,后续调用getCartProducts()直接报错。 - 配置参数未做非空检查:如果
Configuration::get没取到数据库参数,$database/$user/$password会是null,直接传给DbMySQLi会导致连接失败。
修正后的代码示例
public function hookActionPaymentConfirmation($params) { // 先检查必要参数是否存在 $database = Configuration::get('MIMODULOMISMADB_ACCOUNT_NOMBREDB'); $user = Configuration::get('MIMODULOMISMADB_ACCOUNT_USUARIO'); $password = Configuration::get('MIMODULOMISMADB_ACCOUNT_PASSWORD'); // 定义缺失的$campoid变量,根据你的productos表实际字段修改 $campoid = 'referencia'; if (empty($database) || empty($user)) { mail("luilli.guillan@gmail.com", "错误", "数据库配置参数缺失"); return; } // 初始化数据库连接并检查是否成功 $db = new DbMySQLi("localhost", $user, $password, $database, true); if (!$db->connect()) { mail("luilli.guillan@gmail.com", "连接失败", $db->getMsgError()); return; } // 检查订单是否有效 if (!isset($params['id_order']) || !($order = new Order($params['id_order'])) || !Validate::isLoadedObject($order)) { mail("luilli.guillan@gmail.com", "错误", "无效的订单ID"); return; } $products = $order->getCartProducts(); if (empty($products)) { mail("luilli.guillan@gmail.com", "提示", "订单无商品"); return; } foreach ($products as $product) { $id_product = (int)$product['id_product']; $cantidad = (int)$product['cart_quantity']; $referencia = $product['reference']; $product_attribute_id = (int)$product['product_attribute_id']; $newProduct = new Product($id_product); if ($newProduct->hasCombinations() && $product_attribute_id > 0) { // 用getRow获取整行数据,而非getValue $sql = 'SELECT reference FROM product_attribute WHERE id_product_attribute = ' . (int)$product_attribute_id; $rec = $db->getRow($sql); if ($rec && isset($rec['reference'])) { $referencia = $rec['reference']; } } // 用pSQL处理变量避免SQL注入和语法错误 $unidades = $db->getValue('SELECT unidades FROM productos WHERE ' . pSQL($campoid) . ' = "' . pSQL($referencia) . '"'); $unidades = (int)$unidades; $unidadesRestantes = $unidades - $cantidad; $updateSql = 'UPDATE productos SET unidades = ' . (int)$unidadesRestantes . ' WHERE ' . pSQL($campoid) . ' = "' . pSQL($referencia) . '"'; if (!$db->Execute($updateSql)) { mail("luilli.guillan@gmail.com", "更新失败", "SQL: " . $updateSql . " 错误: " . $db->getMsgError()); } else { mail("luilli.guillan@gmail.com", "更新成功", "商品" . $referencia . "库存从" . $unidades . "变为" . $unidadesRestantes); } } }
排查步骤建议
- 先补全
$campoid变量,赋值为你productos表中对应商品编码的字段名,比如'codigo'或者'referencia'。 - 开启PrestaShop调试模式:在
config/defines.inc.php里把_PS_MODE_DEV_设为true,能直接看到具体报错信息,比邮件调试高效得多。 - 单独测试数据库连接:写一段简单代码验证配置参数能不能正常连上目标数据库,先排除连接问题。
- 逐步调试:先注释循环里的SQL操作,只保留邮件输出订单、商品信息,确认钩子能正常触发,再逐步加回数据库操作。
内容的提问来源于stack exchange,提问作者raposo
相关产品推荐
相关产品推荐

