如何让PDO绑定的NOW()函数按PostgreSQL自定义伪造逻辑执行?
让自定义NOW()函数在参数绑定场景生效的解决方案
问题根源
你遇到的核心问题是:绑定参数传递的'NOW()'会被PostgreSQL当作字符串字面量,触发系统默认的字符串转timestamp逻辑,而非调用你自定义的NOW()函数。只有当NOW()作为SQL语法的函数调用出现时,才会触发你通过搜索路径伪造的自定义逻辑。
可行解决办法
1. 直接在SQL模板中嵌入NOW()(最优解)
如果能控制MVC库生成的SQL模板,直接把NOW()写进SQL语句里,完全复用你案例1的逻辑:
$pdo->prepare("INSERT INTO table (ts) VALUES (NOW());")->execute();
这种方式最直接,完全符合自定义函数的触发条件,也不存在注入风险。
2. 构造函数调用式的参数传递(适合必须用绑定的场景)
如果必须通过绑定参数实现,可以让SQL执行参数中的函数调用,注意仅适用于固定函数名(避免SQL注入):
$sql = $pdo->prepare("INSERT INTO table (ts) VALUES ((:func))"); $sql->bindValue(':func', 'NOW()', PDO::PARAM_STR); $sql->execute();
这里的SQL语法((:func))会让PostgreSQL把参数值当作SQL表达式解析,从而触发你的自定义NOW()函数。
3. 创建自定义函数别名,通过参数指定调用
在PostgreSQL中创建一个明确的自定义函数,然后通过绑定参数指定函数名:
-- 先在数据库创建别名函数 CREATE OR REPLACE FUNCTION my_custom_now() RETURNS timestamp AS $$ SELECT NOW(); -- 这里会调用你伪造的NOW() $$ LANGUAGE sql;
然后在PHP代码中:
$sql = $pdo->prepare("INSERT INTO table (ts) VALUES ((:func)())"); $sql->bindValue(':func', 'my_custom_now', PDO::PARAM_STR); $sql->execute();
这种方式更安全,也能清晰区分自定义逻辑和系统函数。
4. 绕过MVC自动绑定,执行原生SQL
如果MVC库的自动绑定逻辑无法修改,直接跳过ORM层,执行原生SQL语句,确保NOW()作为函数调用出现在SQL中,而非参数。
补充说明
- 绑定参数的本质是传递数据而非SQL代码,所以
'NOW()'会被当作字符串处理,PostgreSQL的隐式类型转换会把它解析为当前时间,而非调用函数。 PDO::ATTR_EMULATE_PREPARES对PostgreSQL无效,因为PostgreSQL本身支持服务器端预编译,PDO会直接将参数传递给数据库处理,无法通过该设置改变参数解析逻辑。
内容的提问来源于stack exchange,提问作者GammaGames
相关产品推荐
相关产品推荐

