I am trying to get the output of the lat and lon coordinates from ios (this is working fine), send it to php to query with MySQL and have the php emit an xml document back to io
Since you're new to PHP, I thought I'd record my observations on your script by walking through it line-by-line:
{ $lat = (float)$_GET['lat']; }
{ $lon = (float)$_GET['lon']; }
The braces here are superfluous. You might also wish to perform some input sanity checks (including whether the parameters were set at all).
$minlat = $lat-.1;
$maxlat = $lat+.1;
$minlon = $lon-.1;
$maxlon = $lon+.1;
If you're looking to search for records within some range on the ground, you will want to calculate great-circle distance; you should be aware that, with your current approach, the distance of 0.1° longitude varies with one's latitude, from no distance whatsoever at the poles to almost 7 miles at the equator.
Google have written a useful guide under Creating a Store Locator with PHP, MySQL & Google Maps: pay particular attention to the section on Finding Locations with MySQL and (in your case) Outputting XML with PHP.
Place the rest of the code in one or more try { ... }
blocks and catch any exceptions thrown.
$dbh = new PDO('(censored personal information)');
Check that it succeeded: if (!$dbh) die('Unable to create PDO object');
.
Then set this PDO object to raise exceptions $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
and not merely to emulate prepared statements $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
.
$sql = 'SELECT lat, lon, name FROM locations WHERE lat >= ? AND lat <= ? AND lon >= ? AND lon <= ?';
Whilst your query may well change dramatically following the advice above, it may still be useful to know that you can abbreviate this query using MySQL's BETWEEN ... AND ... operator: WHERE (lat BETWEEN ? AND ?) AND (lon BETWEEN ? AND ?)
.
You might also find your code easier to maintain if you use named parameters instead of placeholders: WHERE (lat BETWEEN :minlat AND :maxlat) AND (lon BETWEEN :minlon AND :maxlon)
.
$params = array( $minlat, $maxlat, $minlon, $maxlon );
If using named placeholders, you could use an associative array as $params = array ( ':minlat' => $minlat, ... );
.
In either case, you could bind values or variables to your parameters separately (which is my preferred approach, as it easily enables one to run the query again with only some parameters changed): $q->bindParam(':minlat', $minlat);
etc.
$q = $dbh->prepare( $sql );
$q->execute( $params );
$doc = new DOMDocument();
Check that it succeeded: if (!$doc) die('Unable to create DOMDocument object');
.
$r = $doc->createElement( "locations" );
$doc->appendChild( $r );
foreach ( $q->fetchAll() as $row) {
fetchAll()
fetches the entire resultset into PHP, which could require a lot of memory if the resultset is large. Where one merely wishes to iterate over each record in turn, it's usually better to fetch each record as required: while ( $row = $q->fetch() )
.
{
This brace (together with its pair below) is superfluous.
$e = $doc->createElement( "location" );
$e->setAttribute( 'name', $row['name'] );
$e->setAttribute( 'd', $d );
Where is your $d
variable declared/assigned?
$r->appendChild( $e );
}
As mentioned above, this brace is superfluous.
}
print $doc->saveXML();