我正在使用来自http://www.movable-type.co.uk的Chris Veness的脚本我试图使用他的Bounding Circle脚本对MySQL数据库运行查询以仅返回属于给定半径的行。如下:
<?php
require 'inc/dbparams.inc.php'; // defines $dsn, $username, $password
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$lat = $_GET['lat']; // latitude of centre of bounding circle in degrees
$lon = $_GET['lon']; // longitude of centre of bounding circle in degrees
$rad = $_GET['rad']; // radius of bounding circle in kilometers
$R = 6371; // earth's mean radius, km
// first-cut bounding box (in degrees)
$maxLat = $lat + rad2deg($rad/$R);
$minLat = $lat - rad2deg($rad/$R);
// compensate for degrees longitude getting smaller with increasing latitude
$maxLon = $lon + rad2deg($rad/$R/cos(deg2rad($lat)));
$minLon = $lon - rad2deg($rad/$R/cos(deg2rad($lat)));
$sql = "Select Id, Postcode, Lat, Lon,
acos(sin(:lat)*sin(radians(Lat)) + cos(:lat)*cos(radians(Lat))*cos(radians(Lon)-:lon)) * :R As D
From (
Select Id, Postcode, Lat, Lon
From MyTable
Where Lat Between :minLat And :maxLat
And Lon Between :minLon And :maxLon
) As FirstCut
Where acos(sin(:lat)*sin(radians(Lat)) + cos(:lat)*cos(radians(Lat))*cos(radians(Lon)-:lon)) * :R < :rad
Order by D";
$params = array(
'lat' => deg2rad($lat),
'lon' => deg2rad($lon),
'minLat' => $minLat,
'minLon' => $minLon,
'maxLat' => $maxLat,
'maxLon' => $maxLon,
'rad' => $rad,
'R' => $R,
);
$points = $db->prepare($sql);
$points->execute($params);
?>
<html>
<table>
<? foreach ($points as $point): ?>
<tr>
<td><?= $point->Postcode ?></td>
<td><?= number_format($point->D,1) ?></td>
<td><?= number_format($point->Lat,3) ?></td>
<td><?= number_format($point->Lon,3) ?></td>
</tr>
<? endforeach ?>
</table>
</html>
我在我的数据库中重命名了我现有的列以匹配Chris Veness使用的列 - 而不是使用$ _GET值,我输入了一些静态值
这不起作用......而且,我找不到一个解决方案为什么它不起作用,确切地说......虽然我认为@ dan08非常关注某些事情他的回答如下。他比我更了解这些东西。
尽管如此 - 我[终于]有一个有效的解决方案!请参阅下面的答案。
答案 0 :(得分:1)
Google Devs的那些人很聪明!
所以这是我找到解决方案的链接:Creating a Store Locator with PHP, MySQL & Google Maps
尽管本教程适用于使用Google Maps API,但本教程的前半部分重点介绍如何使用PHP查询数据库并创建边界圆,以便搜索给定半径内的匹配并仅返回那些匹配的结果。
在本教程中,查询非常快,并以XML格式输出结果,这对于集成到API非常有用。我不需要那个功能,所以我简化了一点。
这就是我所拥有的 - 它完全符合我的需要:
创建一个名为的页面: phpsqlsearch_dbinfo.php
<?
$username="Your_Database_Username";
$password="Your_Database_Password";
$database="The_Name_of_Your_Database";
?>
创建一个名为的新页面: phpsqlsearch_genxml.php
访问此页面时,我们会向其传递一些值,因为我们正在使用$ _GET来收集&#39; lat,&#39; lng&#39;和&#39; radius&#39;值。
EG的 phpsqlsearch_genxml.php LAT = 37安培;?LNG = -122&安培;半径= 25 强>
<?php
require("phpsqlsearch_dbinfo.php");
// Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Opens a connection to a mySQL server
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) {
die("Not connected : " . mysql_error());
}
// Set the active mySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ("Can\'t use db : " . mysql_error());
}
// Search the rows in the markers table
$query = sprintf("SELECT id, address, name, lat, lng, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM candidates HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($radius));
$result = mysql_query($query);
if (!$result) {
die("Invalid query: " . mysql_error());
}
while ($row = @mysql_fetch_assoc($result)){
$ID = mysql_real_escape_string($row['id']);
$name = mysql_real_escape_string($row['name']);
$address = mysql_real_escape_string($row['address']);
$lat = mysql_real_escape_string($row['lat']);
$lng = mysql_real_escape_string($row['lng']);
$distance = mysql_real_escape_string($row['distance']);
echo $name .", ". $address .", Latitude:". $lat .", Longitude:". $lng .", Distance From Home = ". round($distance)." Miles <br /><br />";
// I then insert these matches into a new table for later use.
$new = "INSERT INTO matrix (Marker_ID, Cand_Name, Distance)
VALUES ('$ID', '$name', '$distance')";
$resulting = mysql_query($new);
if (!$resulting) {
die("Invalid query: " . mysql_error());
}
}
?>
最后,要使此示例正常工作,您需要设置数据库。 如果您无法访问phpMyAdmin或者更喜欢使用SQL命令,那么这里是创建表的SQL语句:
CREATE TABLE `markers` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 60 ) NOT NULL ,
`address` VARCHAR( 80 ) NOT NULL ,
`lat` FLOAT( 10, 6 ) NOT NULL ,
`lng` FLOAT( 10, 6 ) NOT NULL
) ENGINE = MYISAM ;
现在填充表的示例数据:Click Here - 此示例数据集总共包含169行。如果您按照上面的链接,您可以按以下格式复制完整数据集:
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Frankie Johnnie & Luigo Too','939 W El Camino Real, Mountain View, CA','37.386339','-122.085823');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Amici\'s East Coast Pizzeria','790 Castro St, Mountain View, CA','37.38714','-122.083235');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Kapp\'s Pizza Bar & Grill','191 Castro St, Mountain View, CA','37.393885','-122.078916');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Round Table Pizza: Mountain View','570 N Shoreline Blvd, Mountain View, CA','37.402653','-122.079354');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Tony & Alba\'s Pizza & Pasta','619 Escuela Ave, Mountain View, CA','37.394011','-122.095528');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Oregano\'s Wood-Fired Pizza','4546 El Camino Real, Los Altos, CA','37.401724','-122.114646');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Round Table Pizza: Sunnyvale-Mary-Central Expy','415 N Mary Ave, Sunnyvale, CA','37.390038','-122.042034');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Giordano\'s','730 N Rush St, Chicago, IL','41.895729','-87.625411');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Filippi\'s Pizza Grotto','1747 India St, San Diego, CA','32.723831','-117.168326');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Lou Malnati\'s Pizzeria','439 N Wells St, Chicago, IL','41.890346','-87.633927');
etc...
etc...
我希望这可以帮助那些和我一样挣扎的人。通过对PHP和MySQL的基本了解,您可以立即启动并运行它。
祝你好运!
答案 1 :(得分:0)
我认为罪魁祸首在于$ sql函数内部的计算。
正确。但这不是你在想什么。
您的主要问题是您在select子句中使用占位符谎言:lat
。 This comment很好地解释了这个问题。但最重要的是你不能在SELECT和FROM子句中绑定params,因为它们在添加参数之前被解析。
使用PDO或MySQLi不会改变它。因此,要将这些变量添加到SELECT子句中,请正确清理它们并在查询中将它们作为字符串插入。
您正在使用我最喜欢的PDO功能之一,命名占位符。所以我建议坚持使用PDO。
要调试500错误,您需要检查服务器日志。如果你有一个典型的LAMP堆栈,也许/var/log/apache2/error.log
。