【问题标题】:Convert a MYSQL* query into a PDO ready statement with placeholders将 MYSQL* 查询转换为带有占位符的 PDO 就绪语句
【发布时间】:2014-04-02 20:26:09
【问题描述】:

我在将 SQL 查询从 mysql 转换为 PDO 准备语句时遇到了麻烦。如下,用于计算存储在会话中的坐标(用户位置)与数据库中的坐标之间的距离,以及是否在用户确定的半径内:

$query = "
SELECT 
* 
FROM 
first_page_data 
WHERE 
((((acos(sin((".$_SESSION['alat']."*pi()/180)) * 
sin(('geo_lat1'*pi()/180))+cos((".$_SESSION['alat']."*pi()/180)) * 
cos(('geo_lat1'*pi()/180)) * cos(((".$_SESSION['alon']."- 'geo_lon1') * 
pi()/180))))*180/pi())*60*1.1515) * (1.609344/1000)) < ".$_SESSION['aradius'];

我想将会话变量、geo_lat 和 geo_lon 变量更改为占位符,以便我可以将值绑定到它们,但我一辈子都无法让它工作!

我什至不知道如何查看我的进展情况,因为一旦我用占位符替换了上面的变量(我一直在使用未命名的问号占位符)然后将值绑定到它们,我不知道如何从中检索已编译的查询$stmt 在我执行之前:

$stmt = db->prepare($query);
$stmt->bindValue(1, $_SESSION['alat'], PDO::PARAM_STR);
**more bindings**
$stmt->execute();   

【问题讨论】:

  • 请向我们展示您尝试过的确切代码,然后告诉我们您尝试后会发生什么。
  • 为什么要在执行查询之前检索编译好的查询?
  • 然后进行更改。我建议使用 names 作为占位符。使用占位符,您不会看到“带有值的查询”。万岁!

标签: php mysql sql pdo


【解决方案1】:

这些变化非常微不足道。我输入了占位符名称,删除了字符串连接,并删除了不正确的引号。它可以使用格式化帮助,或者可能是 UDF。

# Change string-concat for placeholders
$query = "
SELECT 
* 
FROM 
first_page_data 
WHERE 
((((acos(sin(( :lat1 *pi()/180)) * 
sin((geo_lat1*pi()/180))+cos(( :lat2 *pi()/180)) * 
cos((geo_lat1*pi()/180)) * cos((( :lon - geo_lon1) * 
pi()/180))))*180/pi())*60*1.1515) * (1.609344/1000)) < :rad";

# Bind values (PARAM_STR is default)
# While PDO does support using a named parameter multiple times
# when emulating placeholders, this is not guaranteed. To be safe,
# here the code is binding the same value to two "different" params.
$stmt = db->prepare($query);    
$stmt->bindValue(":lat1", $_SESSION['alat']);
$stmt->bindValue(":lat2", $_SESSION['alat']);
$stmt->bindValue(":lon", $_SESSION['along']);
$stmt->bindValue(":rad", $_SESSION['aradius']);

# Execute! I recommend enabling PDO Exceptions to avoid so much
# manual error-checking of result values.
$stmt->execute();   

现在,没有直接的方法来查看语句 with 数据,因为这不是占位符的工作方式 - 即使 PDO 在内部模拟占位符,它也只是一个实现细节,而您没机会看到。

但是,对于How to debug PDO database queries? 中讨论的“调试语句”这一更一般的任务,有多种解决方案(我建议将数据库日志记录用于开发,因为您的代码可能不应该进行日志记录或直接打印查询。)

【讨论】:

  • 让我失望的是字符串连接!也感谢您的建议 - v.helpful :)
  • @Giovanni 不客气!切换到占位符万岁 - 你的代码现在更整洁、更安全:)
  • ps 是 PDO 中的一个已知问题,同一个占位符不能在不同的地方使用吗?原因是我实际上有 geo_lat2 和 geo_lat3 在“或”中添加到这个查询中,所以当我添加这些时,我最终会得到 6 个占位符,所有这些都指的是 $_SESSION['alat'] !!
  • @Giovanni 如果 PDO 正在使用ATTR_EMULATE_PREPARES 那么它将允许在查询中使用占位符进行复制,因为 PDO 本身会生成最终的 SQL,并且它会处理这种情况。有关其他注意事项,请参阅 PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?
  • @Giovanni 也许有一种方法可以简化查询或使用 UDF/函数?如果将 SELECT inside 放在一个函数中,那么在调用时,该函数的参数只会绑定一次,但可以在函数内多次使用。同样,可以在条件中直接调用 UDF 并替换长数学公式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
相关资源
最近更新 更多