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

PrestaShop 1.7中Db::getInstance()->Affected_Rows()返回值异常求助

PrestaShop 1.7迁移后UPDATE语句受影响行数异常问题

问题现象

  • 从PrestaShop 1.6迁移到1.7后,某条UPDATE语句执行时,Db::getInstance()->Affected_Rows()返回大于0的数值(如94),但直接在MySQL中执行该SQL,实际受影响行数为0。
  • 仅该语句和另一语句存在此问题,尝试重新连接数据库无效。
  • 打印DbPDO对象发现last_query字段并非目标UPDATE语句,而是一条查询店铺URL的SQL:SELECT domain, domain_ssl FROM ps17_shop_url WHERE main = 1 AND id_shop = 1 LIMIT 1。

涉事代码

<?php
include(dirname(__FILE__).'/config/config.inc.php');
//products without imgs
$sql9="
UPDATE `"._DB_PREFIX_."product_shop` ps 
SET ps.`dm_google_active` = '0' 
WHERE ps.id_product IN (         
SELECT * FROM (Select DISTINCT(ps.id_product) 
from `"._DB_PREFIX_."product_shop` ps
LEFT JOIN `"._DB_PREFIX_."image_shop` pi 
ON pi.id_product=ps.id_product
WHERE pi.id_product IS NULL) AS wihoutImg
)";
    
if (!Db::getInstance()->execute($sql9)) {
    die('error! removing products without imgs from XML google');
} else {
     echo "Cron [removing products without imgs from XML google] done. <br> -> Rows Afected: ".Db::getInstance()->Affected_Rows()."</br>";
 }

执行输出

Cron [removing products without imgs from XML google] done. -> Rows Affected: 94

DbPDO对象打印信息

DbPDO Object ( [link:protected] => PDO Object ( ) [result:protected] => PDOStatement Object ( 
[queryString] => UPDATE `ps17_product_shop` ps SET ps.`dm_google_active` = '0' WHERE ps.id_product IN ( SELECT * FROM (Select DISTINCT(ps.id_product) from `ps17_product_shop` ps LEFT JOIN `ps17_image_shop` pi ON pi.id_product=ps.id_product WHERE pi.id_product IS NULL) AS wihoutImg ) ) 
[server:protected] => *** 
[user:protected] => *** 
[password:protected] => *** 
[database:protected] => *** 
[is_cache_enabled:protected] => 
[last_query:protected] => SELECT domain, domain_ssl FROM ps17_shop_url WHERE main = 1 AND id_shop = 1 LIMIT 1 
[last_query_hash:protected] => [last_cached:protected] => ) 

问题原因与解决办法

原因分析

  1. PrestaShop 1.7启动时会自动执行一些内部查询(比如获取店铺URL配置),这些查询会覆盖全局Db实例的last_query记录,同时Affected_Rows()方法依赖于最后一次执行的查询,导致返回的不是目标UPDATE语句的结果。
  2. 原UPDATE语句没有过滤已为0的记录,即使MySQL实际未修改任何行,execute()仍会返回成功,但后续内部查询的干扰让Affected_Rows()返回了错误数值。

解决步骤

1. 立即获取目标语句的受影响行数

修改代码,在执行UPDATE后直接从语句对象获取受影响行数,避免被后续内部查询覆盖:

<?php
include(dirname(__FILE__).'/config/config.inc.php');
//products without imgs
$sql9="
UPDATE `"._DB_PREFIX_."product_shop` ps 
SET ps.`dm_google_active` = '0' 
WHERE ps.id_product IN (         
SELECT * FROM (Select DISTINCT(ps.id_product) 
from `"._DB_PREFIX_."product_shop` ps
LEFT JOIN `"._DB_PREFIX_."image_shop` pi 
ON pi.id_product=ps.id_product
WHERE pi.id_product IS NULL) AS wihoutImg
) AND ps.dm_google_active != '0'"; // 只修改需要变更的记录,让行数统计更准确
       
$db = Db::getInstance();
$stmt = $db->execute($sql9);
if (!$stmt) {
    die('error! removing products without imgs from XML google');
} else {
    // 从执行后的PDO语句对象获取真实受影响行数
    $affectedRows = $db->result->rowCount();
    echo "Cron [removing products without imgs from XML google] done. <br> -> Rows Affected: ".$affectedRows."</br>";
}

2. 使用独立Db连接(可选)

如果是Cron任务,可创建独立Db实例,避免和系统内部查询共用全局实例:

// 替代Db::getInstance(),创建独立连接
$db = new DbPDO(_DB_SERVER_, _DB_USER_, _DB_PASSWD_, _DB_NAME_);
$stmt = $db->execute($sql9);
$affectedRows = $db->result->rowCount();

3. 验证SQL逻辑

直接在MySQL中执行带AND ps.dm_google_active != '0'的SQL,确认实际受影响行数,确保和代码返回值一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:20:39