Skip to content

GeoCool!

Web 2.0 and the programmable web that I and others have been talking about for a while has mostly been vapourware so far. There are a few generic components that are useful, but it is somewhat limited what you can do with them. And yes, you may consider this a somewhat biased view, but I think Yahoo!'s new geocoding platform is a huge step in the right direction.


There is of course the fancy new maps.yahoo.com/beta site which is fun, but as far as I am concerned the killer app here is the geocoding platform that drives this. And it is completely accessible for anyone to use. It's also a sane API that anybody can figure out in minutes. Here are a few tips for using this API from PHP 5.


Step 0 - The raw geocoding API

Whenever I do anything with web services, I always add a request caching layer. So here are the base building blocks implemented in 2 functions. One for doing request caching and the second to do the actual REST query to the geocoding service.

<?php
function request_cache($url$dest_file$timeout=43200) {
  if(!
file_exists($dest_file) || filemtime($dest_file) < (time()-$timeout)) {
    
$stream fopen($url,'r');
    
$tmpf tempnam('/tmp','YWS');
    
file_put_contents($tmpf$stream);
    
fclose($stream);
    
rename($tmpf$dest_file);
  }
}

function 
yahoo_geo($location) {
  
$q 'http://api.local.yahoo.com/MapsService/V1/geocode';
  
$q .= '?appid=rlerdorf&location='.rawurlencode($location);
  
$tmp '/tmp/yws_geo_'.md5($q);
  
request_cache($q$tmp43200);
  
libxml_use_internal_errors(true);
  
$xml simplexml_load_file($tmp); 
  
$ret['precision'] = (string)$xml->Result['precision'];
  foreach(
$xml->Result->children() as $key=>$val) {
    if(
strlen($val)) $ret[(string)$key] =  (string)$val;
  } 
  return 
$ret;
}
?>
The above code is the contents of geo.inc which you will see included in the following examples.


Easy enough? No real tricks here. We simply send a regular GET request to http://api.local.yahoo.com/MapsService/V1/geocode with the location parameter set to an address. You can try it yourself directly from your browser by clicking here:

http://api.local.yahoo.com/MapsService/V1/geocode?appid=rlerdorf&location=701%20First%20Ave,%2094089


You can read more about the geocoding service here:

http://developer.yahoo.net/maps/rest/V1/geocode.html


Step 1 - Writing your first application

We can just toss a form around this and dump the results to make sure things are working.

<html>
<head>
<title>GeoCoding API Example</title>
</head>
<body>
<form action="/php/ymap/geo1.php" method="GET">
<input type="text" size="80" name="location" />
</form>
<?php
include './geo.inc';
if(!empty(
$_REQUEST['location'])) {
  
$a yahoo_geo($_REQUEST['location']);
  echo 
"<pre>"print_r($a); echo "</pre>";
}
?>
</body></html>
You can see this one in action here:

http://lerdorf.com/php/ymap/geo1.php


Note how it is able to fill in missing details for a partial address. eg.

http://lerdorf.com/php/ymap/geo1.php?location=701+First+Avenue+94089

results in:

    [precision] => address
    [Latitude] => 37.416384
    [Longitude] => -122.024853
    [Address] => 701 FIRST AVE
    [City] => SUNNYVALE
    [State] => CA
    [Zip] => 94089-1019
    [Country] => US
This means that you can use it for a bunch of different things. Address to lat/long, of course, but also address to city, or city to zip code conversions. Or 5-digit zip to 5+4. This is of course rather US-centric right now, but that will improve over time.



Step 2 - Adding a map

The geocoding is cool, but an actual map is cooler. Easy enough:

<html><head>
<script type="text/javascript" src="http://api.maps.yahoo.com/v2.0/fl/javascript/apiloader.js"></script>
<style type="text/css">
#mapContainer { 
height: 600px; 
width: 800px; 

</style> 
<title>GeoCoding API Example</title>
</head><body>
<form action="/php/ymap/geo2.php" method="GET">
<input type="text" size="80" name="location" />
</form>
<?php
include './geo.inc';
if(!empty(
$_REQUEST['location'])) {
  
$a yahoo_geo($_REQUEST['location']);
  echo 
"[ {$a['Latitude']}, {$a['Longitude']} ] {$a['precision']}-level coordinate accuracy<br />\n";
  if(!empty(
$a['Address'])) echo $a['Address'].', ';
  if(!empty(
$a['City'])) echo $a['City'].', ';
  if(!empty(
$a['State'])) echo $a['State'].' ';
  if(!empty(
$a['Zip'])) echo $a['Zip'].' ';
  if(!empty(
$a['Country'])) echo $a['Country'].' ';
}
?>
<div id="mapContainer"></div>
<script type="text/javascript">
var latlon = new LatLon(<?php echo $a['Latitude']?><?php echo $a['Longitude']?>);
var map = new Map("mapContainer", "rlerdorf", latlon, 3);
map.addTool( new PanTool(), true );
</script>
We are using the Flash-Javascript API here. Try it out!

http://lerdorf.com/php/ymap/geo2.php?location=701+First+Avenue%2C+94089

And yes, of course the map is draggable. The PanTool() part of the above script adds the panning feature.


This is an API that lets you embed a Flash-based map, but control it with Javascript. It's quite cool even if you think Flash sucks. It is described at:

http://developer.yahoo.net/maps/flash/jsGettingStarted.html

and the AJAX-DHTML API is described at:

http://developer.yahoo.net/maps/ajax/index.html


Step 3 - Making the map prettier

The map looks a bit bare. We don't see our address marker, for example. So let's add that.

<html><head>
<script type="text/javascript" src="http://api.maps.yahoo.com/v2.0/fl/javascript/apiloader.js"></script>
<style type="text/css">
#mapContainer { 
height: 600px; 
width: 800px; 

</style> 
<title>GeoCoding API Example</title>
</head><body>
<form action="/php/ymap/geo3.php" method="GET">
<input type="text" size="80" name="location" />
</form>
<?php
include './geo.inc';
if(!empty(
$_REQUEST['location'])) {
  
$a yahoo_geo($_REQUEST['location']);
  echo 
"[ {$a['Latitude']}, {$a['Longitude']} ] {$a['precision']}-level coordinate accuracy<br />\n";
  
$mtitle ''
  if(!empty(
$a['Address'])) { 
    echo 
$a['Address'].', '
    
$mtitle $a['Address'];
  }
  if(!empty(
$a['City'])) {
    echo 
$a['City'].', ';
    if(!
$mtitle$mtitle $a['City'];
  }
  if(!empty(
$a['State'])) echo $a['State'].' ';
  if(!empty(
$a['Zip'])) echo $a['Zip'].' ';
  if(!empty(
$a['Country'])) echo $a['Country'].' ';
  
$info str_replace("\n",'',nl2br(print_r($a,true)));
}
?>
<div id="mapContainer"></div>
<script type="text/javascript">
var latlon = new LatLon(<?php echo $a['Latitude']?><?php echo $a['Longitude']?>);
var mymap = new Map("mapContainer", "rlerdorf", latlon, 3);
mymap.addTool( new PanTool(), true );
marker1 = new CustomPOIMarker('A','<?php echo $mtitle?>', '<?php echo $info?>', '0x0012f0', '0x88CCFF'); 
mymap.addMarkerByLatLon(marker1, latlon);
</script>
</body></html>
There is a lot of stuff there, but all I really changed was a bit of code related to picking information out of the address so I can fill in the expanded marker, and then the marker code. The last 2 lines of the Javascript there that creates a new CustomPOIMarker and then uses addMarkerByLatLon to the map does the trick. When you mouse over it, it will expand to show the title ($mtitle) and when you click on it, it will show the contents of $info.



Step 4 - But but, why Flash?

Aside from portability and less DHTML browser quirks, it gives us widgets! We can add the Navigation widget very easily. 2 lines of Javascript:

  navWidget = new NavigatorWidget(); 
  mymap.addWidget(navWidget); 
That's all. Have a look at it now:

http://lerdorf.com/php/ymap/geo4.php?location=701+First+Avenue%2C+94089



But if the thought of Flash still makes your skin crawl. No worries. You can get pretty close to the Flash version with straight DHTML. Here is the geo4 demo using the DHTML-AJAX API:

http://lerdorf.com/php/ymap/dgeo4.php?location=701+First+Avenue%2C+94089



Step 5 - Something real and useful

By using nothing more than what I have showed so far you can build this:

http://lerdorf.com/php/ymap/yquakes.php

This uses the simple_rss parser I wrote a while ago. You can see the source for the RSS parser here:

http://lerdorf.com/php/simple_rss.phps

The code then just loops through the entries for the earthquakes and adds a marker for each quake. A very simple little application:

<html><head>
<script type="text/javascript" src="http://api.maps.yahoo.com/v2.0/fl/javascript/apiloader.js"></script>
<style type="text/css">
#mapContainer { 
height: 600px; 
width: 800px; 

</style> 
<?php
include '/usr/local/php5/lib/php/simple_rss.php';

$url 'http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml';
$feed rss_request($url$timeout=3600);
echo <<<EOB
<title>{$feed['title'][0]}</title>
</head><body>
<h1>
{$feed['title'][0]}</h1>
<p><font size="+2">
{$feed['description'][0]}<br />
{$feed['pubDate'][0]}</font></p>
EOB;
?>
<div id="mapContainer"></div>
<script type="text/javascript">
var latlon = new LatLon(37.416384, -122.024853);
var mymap = new Map("mapContainer", "rlerdorf", latlon, 13);
mymap.addTool( new PanTool(), true );
navWidget = new NavigatorWidget(); 
mymap.addWidget(navWidget); 
<?php 
  $i 
0;
  while(!empty(
$feed[$i])) {
    
$info  $feed[$i]['description'][0]."<br />";
    
$info .= '<a href="'.$feed[$i]['link'][0].'">'.$feed[$i]['link'][0]."</a>";
?>  
mymap.addMarkerByLatLon(
   new CustomPOIMarker('<?php echo $i?>',     '<?php echo $feed[$i]['title'][0]?>', '<?php echo $info?>', '0x0012f0', '0xFFFFFF'),
   new LatLon(<?php echo $feed[$i]['lat'][0].','.$feed[$i]['long'][0]?>));
<?php
    $i
++;
  }
?>
</script>


You can also let the API figure out your markers for you which makes this even simpler. If the RSS feed is using georss correctly you can use the GeoRSSOverlay mechanism. Here it is using the earthquake RSS feed directly:

http://lerdorf.com/php/ymap/rssquakes.php

And here is the code. I am still loading the RSS feed myself from PHP because I want to get the pubDate and title from it, but everything else is handled automatically.

<html><head>
<script type="text/javascript" src="http://api.maps.yahoo.com/v2.0/fl/javascript/apiloader.js"></script>
<style type="text/css">
#mapContainer { 
height: 600px; 
width: 800px; 

</style> 
<?php
include '/usr/local/php5/lib/php/simple_rss.php';

$url 'http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml';
$feed rss_request($url$timeout=3600);
echo <<<EOB
<title>{$feed['title'][0]}</title>
</head><body>
<h1>
{$feed['title'][0]}</h1>
<p><font size="+2">
{$feed['description'][0]}<br />
{$feed['pubDate'][0]}</font></p>
EOB;
?>
<div id="mapContainer"></div>
<script type="text/javascript">
var latlon = new LatLon(37.416384, -122.024853);
var mymap = new Map("mapContainer", "rlerdorf", latlon, 13);
mymap.addTool(new PanTool(), true);
navWidget = new NavigatorWidget(); 
mymap.addWidget(navWidget); 
overlay = new GeoRSSOverlay('http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml');           
mymap.addOverlay(overlay);
</script>
</body></html>

There are an amazing number of things you can do with this API. What I have described here is just the surface of it. Overlays and events can do nifty things. You can even get at the low-level tile api directly using this:

http://developer.yahoo.net/maps/rest/V1/mapImage.html

I am very much looking forward to see what people out there end up doing with this. I timed how long it took me to write the Earthquake mapping application above. 21 minutes from the time I started looking for the geotagged earthquake data until I was happy with the final app. And that included normal office interruptions and tracking down a dumb syntax error. Note also that any local.yahoo search through the API now includes lat/long info and Flickr has lat/long information as well. And even if a service doesn't provide geotags, as long as they provide addresses you can use the geocoding api to get the lat/long data and do interesting geospatial things with it. Getting to the point where we have full and trivial control over geocoding and mapping opens up a whole new class of application.

Trackbacks

Jeremy Zawodny's blog on : How To Use the Yahoo Geocoding API in PHP

Show preview
You know you've got some cool APIs when Rasmus takes the time to write some code against them and then show the world how easy it is: GeoCool! Web 2.0 and the programmable web that I and others have been talking about for a while has mostly been vapourware so far. There are a few generic components that are useful, but it is somewhat limited what you can do with them. And yes, you may consider this a somewhat biased...

Darkness Productions' Log on : Rasmus Lerdorf Writes PHP Functions Based on Yahoo! APIs

Show preview
Rasmus Lerdorf (you might know him as the guy who started PHP) has written some code to work with the new APIs Yahoo! released for their mapping service. Read about it here....

Spatially Adjusted on : Using the Yahoo Geocoding API with PHP

Show preview
Link - GeoCool!Web 2.0 and the programmable web that I and others have been talking about for a while has mostly been vapourware so far. There are a few generic components that are useful, but it is somewhat limited what...

Bokardo on : Having Fun with APIs

Show preview
PHP creator Rasmus Lerdorf on the new Yahoo Maps API (via Jeremy Zawodny): &#8220;There is of course the fancy new maps.yahoo.com/beta site which is fun, but as far as I am concerned the killer app here is the geocoding platform that drives this. An...

Zz. on : Yahoo! Maps API examples in PHP

Show preview
Rasmus Lerdorf has a post filled with Yahoo! maps API examples: "Web 2.0 and the programmable web that I and others have been talking about for a while has mostly been vapourware so far. There are a few generic components that are useful, but it is som

Jacques Marneweck's Blog on : Less vaporware with Yahoo!'s Rasmus Lerdorf

Show preview
Picked up from Jeremy Zawodny's blog entry titled &quot;How To Use the Yahoo Geocoding API in PHP. You know you've got some cool APIs when Rasmus takes the time to write some code against them and then show the world...

Amit Chakradeo Inc. on : Yahoo Geocoding in ruby&#8230;

Show preview
Find lattitude and longitude of any address Yahoo just released a new beta of their maps webservice. Here is a small ruby script (inspired by this) that I wrote that returns Lattitude, Longitude of the address provided&#8230; require &#8216;open-uri&...

blogZero on : PHP Developer Center

Show preview
The Yahoo! Developer Network has just opened their doors on yet another excellent resource, this time for PHP Developers. The focus thus far is on providing documentation needed to make REST Web Service requests, parse the results (be they in standard X

Comments

Display comments as Linear | Threaded

jon on :

Finally! It was such a friggin' pain in the ass to get good geodata for applications before. I mean, really it couldn't be done without spending a buncha money.

MTheaded on :

Wow. Thank you, Yahoo, and thank you, Rasmus. This tutorial is a real gift -- the best thing I have seen in a long, long time. You just made job a zillion times easier. You rock!

kosso on :

This is absolutely great stuff. Thanks Rasmus! Thanks PHP! Thanks Yahoo! I will now be moving over my map stuff to Flash and Yahoo!, since it's much easier than the Google dhtml way for crossbrowser goodness. PHP+Flash make an awesome pair imho.

kevin on :

Flash and PHP don't make a good pair. PHP is a lot more portable than Flash will ever be. PHP works on multiple platforms, it's not limited to just Windows and Mac.

Flash? Give me an alternative that's free and based on open standards anyday.

Mikel on :

Nice tutorial!

Wonder why you didn't utilize the GeoRSSOverlay method in the API?

http://developer.yahoo.net/maps/flash/V2/flashReference.html#GeoRSSOverlay

Maybe browser security prevents loading RSS from a different domain. In that case, Yahoo could modify the API to accept a blog of geoRSS.

Cheers, Mikel

Rasmus on :

Probably should have mentioned GeoRSSOverlay, but I didn't actually want an overlay. I wanted to show how to fully control all your markers and that you can place markers in places like Fiji directly even though there isn't any map data for Fiji.

Rasmus on :

Ok, I have added a GeoRSSOverlay version of the earthquake demo. It works ok. The double-load of the RSS feed file and the lack of full control of each marker text are the downsides, but it is a bit faster than doing it manually.

A. Nonny Mouse on :

If you have a spare server with tons of space and a not too overly burdened processor, you can create your own geocoder fairly simply using the files from the Tiger project
and the Geo.coder.us project.

Son Nguyen on :

Definitely Flash/JS/XML is faster and more interactive. I guess FAJAX will have even more potential.

Sam Feltus on :

I am a gardener by trade, and just code as a hobby. Nevermind the Open Source issue. I don't understand at all the technical reason that JS is held in higher regard than Flash. (I understand JS has it's uses) Don't know alot about PHP, but in Perl and Python circles, it seems like you are bringing up AIDS or something when you mention Flash. I can't seem to find a decent technical answer, yet plenty of philosophical/cultural ones. Most people who criticize Flash don't seem like they know much about it.

Wolfgang on :

Hey Rasmus,

great stuff, but when do you think will Yahoo support european maps?

best

Wolfgang

Justin on :

Wow, this is an amazing tutorial. Thanks so much!

jcburns on :

Thanks very much for a clear explanation of how to take advantage of these new APIs...another indiction of how useful PHP is in pulling this stuff together, too.

I do have one question:
geo.inc includes a function called file_put_contents that fails on the version of PHP I'm running (PHP/4.3.11)

..the obvious solution is to upgrade PHP, sure, but is there a workaround to using this function?

Thanks.

Rasmus on :

There are a couple of PHP5-specific things here. Even a PHP 5.1-specific bit of code in how request_cache() uses a stream in the file_put_contents() call. But, you can just replace that bit with fopen()/fwrite() to write the data to a file.

Brandon Baunach on :

Hi. Thank you so much! You are awesome! I still can't get the RSS feed example to work. The error I keep getting is in the simple_rss.php file
"
Fatal error: Call to undefined function: apc_fetch() in /home/toptenci/public_html/test/simple_rss.php on line 14"

you can see it live at www.toptencity.com/test/rssmap.php

Also, couldn't you also parse the XML with the simplexml function? How does this work? (I'm new and stupid.) This is the scary side of CMS admins.

Finally, I would like to do a map of bike accidents in san francisco where a form is filled out and info is sent to a MySQL database then retrieved to be displayed on a yahoo map (flash js api) any pointers?

Rasmus on :

You can skip the apc_fetch/apc_store stuff. Just delete that if condition around that big block and delete the apc_store call. APC is a shared memory opcode cache which also has userspace access. What this is doing is caching the parsed XML data in shared memory so subsequent fetches are lightning fast. For most people who aren't performance nutcases like me, you don't need this.

Trev Meier on :

I am having nothing but trouble with this code. I am getting a lot of undefined function errors. The first of which is the file_put_contents() function. I have combined all of the code to run out of a single file, thus taking out the 'include' command. Can anyone re-write my code so that it works! I am new to all of this.


if(!empty($_REQUEST['location'])) {
$a = yahoo_geo($_REQUEST['location']);
echo ""; print_r($a); echo "";
}

function request_cache($url, $dest_file, $timeout=43200) {
if(!file_exists($dest_file) || filemtime($dest_file) < (time()-$timeout)) {
$stream = fopen($url,'r');
$tmpf = tempnam('/tmp','YWS');
file_put_contents($tmpf, $stream);
fclose($stream);
rename($tmpf, $dest_file);
}
}

function yahoo_geo($location) {
$q = 'http://api.local.yahoo.com/MapsService/V1/geocode';
$q .= '?appid=rlerdorf&location='.rawurlencode($location);
$tmp = '/tmp/yws_geo_'.md5($q);
request_cache($q, $tmp, 43200);
libxml_use_internal_errors(true);
$xml = simplexml_load_file($tmp);
$ret['precision'] = (string)$xml->Result['precision'];
foreach($xml->Result->children() as $key=>$val) {
if(strlen($val)) $ret[(string)$key] = (string)$val;
}
return $ret;}

Rasmus on :

I did mention it was PHP 5.1 specific. And that if you don't want to install that version you can emulate file_put_contents() with a simple fopen/fwrite

For forward compatibility stuff like this a good place to look is in pear/PHP_Compat. Either install PHP_Compat or borrow the code from it you need. For file_put_contents(), look here:

http://cvs.php.net/co.php/pear/PHP_Compat/Compat/Function/file_put_contents.php?r=HEAD

Just to be clear. My toys entries here are about showing new things. That means new features in PHP, new toys to connect PHP to and new toys in general. I am not going to spend much time on backward compatibility and writing super-portable code examples.

Bill Donohoe on :

Thanks Rasmus. I have an rss file of properties I would like to publish as an xml file on a map like the one below. It would have 50 points. I also have it joined with an xml file that describes property details such as "year built". I am jazzed.

example

I am learning php5.0 from Bulger, Greenspan and Wall and have tried your replacement method, but had trouble inserting the bigger file due to the comments. You know?

Basil on :

I am just an ordinary guy on the net but I appreciate of what your are and what you did... keep up the good work...

chris on :

great stuff.. HUGE help.. the issue i am having is the script is not writing the temp file. I get a warning-

Warning: /tmp/yws_geo_8fc3419755b1179c0f363802c91d66ef:1: parser error : Document is empty

i am using php 5.0.4
I have created a tmp folder in the same dir as the geo.php file
i am using OS X tiger.

still a newbie with PHP, but 2 hours into troubleshooting this issue myself i am coming up blank, so i thought i would ask.

thanks
c

Rasmus on :

The problem is that I am pushing the envelope a bit and using bleeding-edge features. In this case the line:

file_put_contents($tmpf, $stream);

Where I stream directly from the open file to a file on the disk is the problem. This was a feature added in PHP 5.1. For 5.0.x you can simply do:

function request_cache($url, $dest_file, $timeout=43200) {
if(!file_exists($dest_file) || filemtime($dest_file) < (time()-$timeout)) {
$data = file_get_contents($url);
$tmpf = tempnam('/tmp','YWS');
file_put_contents($tmpf, $data);
rename($tmpf, $dest_file);
}
}

chris on :

That was it! thanks Rasmus.

Brian on :

What about PHP 4.3.10. Am I going to get anywhere? new to PHP
thanks in advance

Brian on :

v4, my bad. Got the sysadmin to move to 5.1.1
I am having problems with the /tmp file on my system however.
I will carry on. Thanks for the example.

Jason Kop on :

I'm also having the same issues as chris. I've made the recommended changes and still recieve the following errors:

Warning: /tmp/yws_geo_0167247cb7c756efaa8e6c327ba578a6:1: parser error : Document is empty in /home/vwebstud/public_html/clients/coastal/map/geo.php on line 17

Warning: in /home/vwebstud/public_html/clients/coastal/map/geo.php on line 17

Warning: ^ in /home/vwebstud/public_html/clients/coastal/map/geo.php on line 17

Warning: /tmp/yws_geo_0167247cb7c756efaa8e6c327ba578a6:1: parser error : Start tag expected, '

Aaron Brazell on :

I'd still like to see a better version of Visual Earth's location finder. What VE lacks is an open opportunity for Yahoo. Location finding by wifi API.... A way for me to GET THE RESULTS via code. I don't mind a standalone app as MS has done, but I need a provision where I can get the Lat and Long programmatically. Can Yahoo meet this need?

Rasmus on :

By WIFI API? I have no idea what that means.

Andrew Bidochko on :

I would like to reccoment you to take a look on the Skype E911 Plug-in http://share.skype.com/directory/skype_e911_plug-in/view/
May be it provides some kind of API to get wifi geo information programmatically.

Aaron Brazell on :

MSN's Virtual Earth has the location finder which will attempt to locate where you are by WiFi signal by triangulating to within 60-100m. Or something to that effect.

The problem with MSN's way of doing it is that the standalone applet that runs on the system doesn't return anything particularly useful. It just opens VE in a browser and pinpoints the location.

What I'm saying is that this is cool but lacks an API for programmers to tap into. In other words, it would be nice if there was a way to get the relevant Geocode info and use it in Perl, PHP, Python, .NET, etc.

Specifically, this would be useful for bloggers and more specifically mobile bloggers.

I make the comment here because I prefer if Yahoo perfected this technology instead of Microsoft. That and the VE team has been tremendously unresponsive.

See my entry of Nov 11 for details. http://www.technosailor.com/wifi-as-gps-for-maps

Hope that makes more sense.

Rasmus on :

The biggest problem becomes the Navteq-enforced restrictions on the data here. If you read through the terms of service you will see why this is unlikely to happen.

Eddie V on :

I'm really just starting to pick up PHP and waiting for my hosting provider to upgrade to 5.X, I find Geocoding very fascinating. Using PHP along with the Yahoo APIs, Is it possible to:
This is just an example, but if it's possible, fantastic.
Select an address of a fire company, show on the map.
Create a perimeter of a certain distance ie. 3 miles that fire company supports and find out.
When homeowner goes on web to find out which fire company supports, they plug in their address and it shows which FC would come if their house burned down.

Rasmus on :

That would be pretty easy assuming you have the addresses of the fire stations. Simply convert them to lat/lon and put a marker there. Then when someone enters an address you could do a rough guess by finding their zip code and seeing if it matches any of them and then run through your best guesses and do something like:

function dist($lat1, $lon1, $lat2, $lon2) {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) sin(deg2rad($lat2)) + cos(deg2rad($lat1)) cos(deg2rad($lat2)) cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist
60 * 1.1515;
return $miles;
}

Which will give you the distance in miles between lat1,lon1 and lat2,lon2.

You could also sort the lat/lon sets of the firestations and walk through the array to find the closest one and then do the distance check. Or come up with some other way to optimize it. You may not need any optimization though. Might be easier to just check each one.

TranspoMan on :

Thanks for the tutorial Rasmus, I got it! My brain has expanded to here: http://www.tetonpost.com/states/

Matthew Burton on :

I think I've successfully mimicked the file_put_contents function with this:

fopen($tmpf, 'w+');
fwrite($stream, $tmpf);
fclose($stream);
rename($tmpf, $dest_file);

But I still have a problem running this because simplexml_load_file is also a PHP5 function. Is there another way to do this that doesn't require functions unique to PHP5?

Arn B on :

Bumped into the same issue, PHP4 and come up with this solution:

1. Download and install the XML2Array Class at http://spunge.mirrors.phpclasses.org/browse/file/6211.html You may have to suscribe to get the file. Install it. I had to rename function xml2array(same name as class) to func_xml2array to get it to work for me.

2. Modified Rasmus' code to this and use function yahoo_geo below to get the geocode as follows (Rasmus my apologies if I you feel your code is wrecked. Wihout our example I would have been unable to get this to work, any positive feedback appreciated)

// get exact geo code using yahoo geocoder
if (!$error)
{
$GeoCode = yahoo_geo($Address . " " . $Mailcode);
// echo ""; print_r($GeoCode); echo "";
if ($GeoCode['@precision'] == 'address')
{
$Latitude = "'" . $GeoCode['Latitude']['#text'] . "'";
$Longitude = "'" . $GeoCode['Longitude']['#text'] . "'";
}
}

3. My version of the Yahoo Geocoder for PHP 4

Arnb on :

Previous message chopped if this chops email me and I'll send the code
func_xml2array($Rdata);
$ary= $pars->getResult();
return $ary['ResultSet']['Result'];
}
?>

Arn B on :

I gave up and created this web page with my PHP4 solution

http://www.arnb.org/Geocode.html

Zot on :

This is all quite cool, but nobody has mentioned that it's just for US addresses. What about the rest of the world? A free geocoding service that gave such results would be hugely useful. Or, does the Yahoo service provide that? I couldn't get any success playing with Rasmus' demos.

Jay Blanchard on :

This is an excellent tutorial for this kind of application. My next trick would be to implement this for a limited region. In other words, the client would type in their address and in return they would find out if a particular service was available in their area and the would get a map displaying themselves in relationship to that service area.

Tom Bailey on :

Mr. lerdorf: Thanks for the great article. I thoroughly enjoy your parsimonious approach to coding.

I also stumbled upon your post on AJAX the other day; clean, simple, elegant.

For those of you reading the comments, check it out at:

http://marc.theaimsgroup.com/?l=php-general&m=112198633625636&w=2

Thanks again for sharing your insight and style with those of us climbing the learning curve.

Jason on :

How to get Distance and Time Calc?

Ive not been able to reproduce the calculation provided by Yahoo's results, has anyone else been able to?

Im off by .3

Zach Smith on :

Hey! I created a PHP 5 class based on your script. Thanks for the heads up. Hope you check it out.

http://digg.com/software/Awesome_PHP_Yahoo_Geocoding_Class

Paul on :

I have a serious problem.

When I use geo1.php on this website it returns with the precision ='s address.

When i do the same address using geo1.php on my server it returns with city precision. I have been having this problem the last few days since fooling around with the yahoo geocoder. If anyone can give me a hand that would be great. I really am not sure what is going wrong.

Doh!

SCOTT STREHLI on :

Thanks for the help. I am not very good at this, but was able to get the mapping to work. Hense a testament to you. Quick question: How do I pass the data (adress, state, zip, lat, lon) to another webpage? I usually use hidden values and submit using a form. Any advice.

Thanks.

Scott

Amy on :

Hi,
This is all cool, I want to say thanks for that script.
Thanks
Amy

Neal Hacker on :

I would like to add an GeoRSS XML overlay to this script as a sort of mashup with the keyed in location and pre-existing lat/long values provided by means of xml file.

I am following the information provided by Yahoo:
http://developer.yahoo.com/maps/ajax/index.html#ex30_6

I am using the following line of code:
map.addOverlay
(new YGeoRSS'http://www.streamisp.com/gps/skypilot.xml'));

If I insert this line of code after the 'marker1' variable I get no output. If I insert it after the 'marker1' variable I also get no output and my 'marker1' goes away...

Any thoughts on this??? Anyone???

Richard Lynch on :

I've been playing with this a bit, and it's fun, but it seems a bit weird when you try to get a nice centered global map...

Maybe I'm just being stupid (again) but I tried playing around with various values for:
var latlon = new LatLon($x, $y);
var map = new Map('mapContainer', 'rlerdorf', latlon, 17);

Some values for $x, $y seemed to "move" the center, but others didn't.

Worse, it didn't seem to follow a discernible pattern.

And I certainly have not yet achieved a nice centered world map.

In sheer frustration, I did a CustomPOIMarker at every 30 degrees lat/lon from -90 to 90 and -180 to 180.

Aha!
Any input it doesn't like gets converted to, err, what I would consider -180, 0

And it does not like -90 nor 90 for lat.

I'm still no closer to getting a world map at Map.zoom = 17, but at least it seems a little less psychotic now...

Maybe setting bounds to -89 and 89 for latitudes will work...

Richard Lynch on :

In typical Flash fashion, it would appear that using 0 for a value means something different than 0, it means, "don't do what I asked you to do when moving things around". :-(

I remember fighting this in Ming before...

Grrrrr.

A container of 514x514 and latlon of 1, 1 comes "close enough" to what I wanted -- albeit after an hour of trying a lotta numbers.

Plus, values beyond +/-80 for latitude seem borked... I don't think we can blame that on Flash, but I dunno for sure.

Al McKay on :

I am looking for som simple code to read user input from html form and return just latitude/longitude. Anyone have anything like this lying around?

Steve on :

Do I need to put a pid# in this code in order to get it working on my website?

Please help as I am trying to figure out how to get lat/long coordinates from an address someone types in, its actually a school asignment that I am having some difficulty with, I also need to get the local sunset/sunrise and time. can someone help me please?

Thanks so much..
steve107@sympatico.ca

rentBits on :

Does Google have a free geo code API? If it is not free are there limitations. It is my understanding that Yahoo has some ping limitations and then it will cost more. Is this true?

Dave @ Rentvine on :

Thanks for providing code for this, I do a lot of GeoCoding and this will help me out on my rental site. I am more of a Coldfusion guy but I needed an example in PHP.

GamesForBoys on :

If I insert this line of code after the 'marker1' variable I get no output. If I insert it after the 'marker1' variable I also get no output and my 'marker1' goes away...

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Form options