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

WordPress PHP文件中含STR_TO_DATE的SQL查询返回空结果问题

WordPress $wpdb 查询返回空值的解决方法

先贴出你遇到问题的代码:

$query = $wpdb->prepare("SELECT post_id
FROM {$wpdb->prefix}postmeta t1
WHERE meta_key = 'expiry_date'
AND STR_TO_DATE(meta_value, '%Y-%m-%d') BETWEEN NOW() AND NOW() + INTERVAL 6 MONTH
AND EXISTS (SELECT 1 FROM wp_postmeta t2
            WHERE t2.meta_key = 'customer_email'
            AND t2.meta_value = %s
            AND t2.post_id = t1.post_id)
GROUP BY post_id", 'test@hotmail.co.uk');

$result = $wpdb->get_results( $query, ARRAY_A );

执行这段代码时$result返回空值,问题出在日期转换的条件行:

AND STR_TO_DATE(meta_value, '%Y-%m-%d') BETWEEN NOW() AND NOW() + INTERVAL 6 MONTH

这段查询在phpMyAdmin能正常执行,但在WordPress的PHP文件里只有移除该行才能正常工作,核心原因是**$wpdb->prepare会将SQL语句中的%识别为参数占位符**,你写的%Y-%m-%d里的%会被prepare错误解析,导致最终生成的SQL中日期格式字符串被破坏,无法正确转换日期。

解决办法

把SQL中的%转义为%%,让$wpdb->prepare正确识别这是SQL语法的一部分而非参数占位符,同时可以优化日期匹配逻辑(用CURDATE()替代NOW(),避免时间部分干扰匹配):

$query = $wpdb->prepare("SELECT post_id
FROM {$wpdb->prefix}postmeta t1
WHERE meta_key = 'expiry_date'
AND STR_TO_DATE(meta_value, '%%Y-%%m-%%d') BETWEEN CURDATE() AND CURDATE() + INTERVAL 6 MONTH
AND EXISTS (SELECT 1 FROM {$wpdb->prefix}postmeta t2
            WHERE t2.meta_key = 'customer_email'
            AND t2.meta_value = %s
            AND t2.post_id = t1.post_id)
GROUP BY post_id", 'test@hotmail.co.uk');

$result = $wpdb->get_results( $query, ARRAY_A );

补充说明

  1. 转义%为%%是WordPress$wpdb->prepare的硬性要求,所有SQL语法中的%都需要这样处理,避免和参数占位符冲突。
  2. 用CURDATE()替代NOW()是因为STR_TO_DATE转换后的结果是纯日期(无时间部分),NOW()包含时间会导致当天的日期无法被正确匹配(比如当前时间是2024-05-20 14:30,转换后的日期是2024-05-20 00:00,会小于NOW(),无法进入BETWEEN范围)。如果你的业务需要匹配带时间的日期字符串,可以调整为STR_TO_DATE(meta_value, '%%Y-%%m-%%d %%H:%%i:%%s'),并保持使用NOW()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:31:17