使用PDOStatement ::使用PostGIS函数进行准备

时间:2013-08-21 20:26:38

标签: php pdo prepared-statement postgis

我是PDO的新手,所以如果我误解了一些事情,请原谅。我花了很长时间阅读在线提供的资料,但无法找到合适的解决方案。

我正在尝试编写的代码应该执行以下操作:获取两个包含特定点纬度($ lat)和经度($ lon)的$ _GET变量,然后选择存储在PostGIS中的这些坐标的最近点启用数据库(加上返回该点的距离)。这就是当前(和工作)代码片的样子:

$courts = $pdo->query("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText('POINT($lon $lat)') , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText('POINT($lon $lat)' ) , geog , 20000) ORDER BY distance LIMIT 1");

但是,我想尝试使用prepare语句,因为我读到这些是SQL注入证明。

$courts = $pdo->prepare("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText('POINT( :lon :lat )') , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText('POINT( :lon :lat )' ) , geog , 20000) ORDER BY distance LIMIT 1" );
$courts->execute(array( ':lon' => $lon , ':lat' => $lat ) )

但上面的代码不起作用。执行errorInfo()仅返回以下错误代码:HY093

从我到目前为止所学到的,我假设上面的代码不起作用,因为->prepare占位符只能用于你要正常插入输入参数的地方。

E.g。 ->prepare( "SELECT * FROM x WHERE field=:field" );会奏效 而->prepare( "SELECT * FROM x WHERE field='someprefix:field'" );不会。我上面尝试使用的代码有点类似于“someprefix”-example。

所以,我的问题是,如何在不必使用->query并手动阻止注入的情况下获取我尝试执行的语句。或者我会更好地确保传递的参数是正确的,简单的坐标并使用->query

这只是我在这里提出的第二个问题,请原谅我,如果我对我的研究和提供的信息不够清楚或彻底。

2 个答案:

答案 0 :(得分:2)

我真的想知道如何向新移民提供有关该主题的基本知识。

对于持续的观察者来说,这些问题似乎非常重复。这让程序员想到了网站的低效率。然而,似乎网站政策鼓励重复问题。所以,在这里。

准备好的声明只能代表竞争数据文字。坦率地说 - 一个完整的字符串数字

查看您的代码:

'POINT($lon $lat)'

已经是一个数据文字。所以,你不能让文字成为文字的一部分。你必须将它整合起来:

$courts = $pdo->prepare("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText(:point) , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText(:point ) , geog , 20000) ORDER BY distance LIMIT 1" );
$courts->execute(array( ':point' => "POINT($lon $lat)") );

答案 1 :(得分:2)

执行此操作的最佳方法是创建WKT字符串,而是将坐标浮动直接传递给PostGIS几何构造函数。以下是您的准备陈述应该是什么样的。

SELECT *, ST_ASTEXT(geog), ST_Distance(poi, geog) AS distance
FROM bvbcourts,
 (SELECT ST_MakePoint(:lon, :lat)::geography AS poi) AS f
WHERE ST_DWithin(poi, geog, 20000)
ORDER BY distance
LIMIT 1;