LocalSearch
Client Class in PHP 5 Now let's extend the YahooAPI
class to query the Yahoo! Local Search API. We can easily create a class that manages all this work for us. Instead of the previous procedural code, if we extend the YahooAPI
class and create some appropriately-named methods -- for example locationSearch($query, $location)
-- we can further simplify the process of interacting with the APIs.
I've written an example class that generally covers everything we need for interacting with the Local Search API. It has three main methods: locationSearch
, positionSearch
and extractResults
. Here's the code:
The constructor method sets the basic properties we'll always need for each Local Search API request:
public function __construct()
{
$this->setParam('output','php');
$this->setService('http://local.yahooapis.com/'.
'LocalSearchService/V3/localSearch');
$this->setAppID('your-app-id-here');
}
The two search methods represent different ways of performing a search, depending on whether or not we have a location name or exact GPS coordinates. They simply set the required parameters and call the doAPICall
method of the parent YahooAPI
class:
public function locationSearch($query,$in_location)
{
$this->setParam('query',$query);
$this->setParam('location',$in_location);
return $this->doAPICall();
}
public function positionSearch($lat,$long)
{
$this->setParam('query','*');
$this->setParam('latitude',$lat);
$this->setParam('longitude',$long);
return $this->doAPICall();
}
The extractResults
method saves us entering ['ResultSet']['Result']
all the time when we want to output the results, because the data we need will always be within that part of the returned array:
public function extractResults()
{
$return = $this->getResults();
$return = $return['ResultSet']['Result'];
return $return;
}
}
?>
You'll find a copy of the code in the archive for the article. Keep it handy because we'll be using it in our example mashup. We'll also build a similar class for the Maps API later, as it has some slightly different requirements.
Our example "pizza" search, executed using our new LocalSearch
class, now looks like this:
require_once('localsearch.class.php');
$localSearch = new LocalSearch();
$localSearch->locationSearch('Pizza','Palo Alto, CA');
$output = $localSearch->extractResults();
That's much easier, don't you think?
Yahoo! Maps AJAX API
Perform a quick web search and you could find the web sites for these pizza places, each of which would list the restaurant's address. But why would you go to all that trouble when Yahoo! provides all this data in the returned array -- as well as latitude and longitude information? Here's an example of the data returned:
[Title] => Patxi's Chicago Pizza
[Address] => 441 Emerson St
[City] => Palo Alto
[State] => CA
[Phone] => (650) 473-9999
[Latitude] => 37.445265
[Longitude] => -122.163432
Now that we have the location information, we need to figure out how to plot it on a map. Yahoo! provides a map image API, offering raw images of maps in PNG format, and (in theory) we could use GD to draw markers on the map. However, since we're building a web application, we can instead use the Maps AJAX API to generate a UI-friendly, interactive Yahoo! maps display. We can then add markers to the map in preset positions, using the bundled functions. (Note that the Maps AJAX API isn't really an Ajax API! In fact, there isn't any real Ajax at all -- that is, there are no XMLHttpRequest calls -- but due to the fact that the term Ajax has come to represent any web page technology that uses JavaScript and doesn't need to reload the web page to update itself, Ajax would be the best way to describe it.)
Unlike the other Yahoo! APIs, the Maps AJAX API isn't a REST-based web service. Instead, you have to include a JavaScript file on your page, create an instance of the map in a container on the page (usually a
mapoutput.php
example in the code archive. This is all the JavaScript you'll need to generate the map: var ymap = new YMap(document.getElementById('mC'),YAHOO_MAP_REG);
var mPoint = new YGeoPoint(37.4041960114344,-122.008194923401);
ymap.drawZoomAndCenter(mPoint, 3);
var marker = new YMarker(mPoint);
marker.addLabel('A');
marker.addAutoExpand('
ymap.addOverlay(marker);
The first line creates a new instance of the YMap
class, and assigns it to the element on the page with an ID of 'mC'
. The second argument represents the desired map type, in this case a regular map rather than satellite imagery, YAHOO_MAP_SAT
, or a hybrid of the two, YAHOO_MAP_HYB
. The second line creates a YGeoPoint
object, a point on the map based on latitude and longitude coordinates, while the third line calls the map object and tells it to centre itself on this new point and display the map, at a zoom level of 3.
The final three lines of JavaScript create a YMarker
object, a visual map marker that expands to reveal some extra content when it's moused over. Our challenge is to generate all this with PHP, and to make the job easy, we're going to build a class that generates all the code for us.
Mashup Time!
Now that we've sorted out how to query the APIs and deal with the data, it's mashup time! As I mentioned before, we'll create a simple application that finds places with the local search API and, using the latitude and longitude coordinates from the returned search data, marks the exact locations of these places on a map from the maps API. And of course we'll wrap all the functionality up in a simple PHP class. The AJAX map API uses JavaScript code, so we'll use our PHP class to generate the required JavaScript based on the returned search data.
First, we'll start by querying the Maps API. I'll use the client class for the local search API, which I demonstrated earlier, to execute this sample query: 'Pizza' in 'Palo Alto, CA'. We need an instance of the LocalSearch
class, and we'll use its locationSearch method to execute the API query. The extractResults
method will give us the data that we want to work with. Now that we've built our client classes, all this can be achieved in three lines of code:
$localSearch = new LocalSearch();
$localSearch->locationSearch('Pizza','Palo Alto, CA');
$apiOutput = $localSearch->extractResults();
Let's take a step back for a moment and call print_r($apiOutput)
to see what we have. The array $apiOutput
now contains a number of sub-arrays, each of which is a single search result and contains (among other things) a 'Title', 'Latitude' and 'Longitude'. That's all we need for the moment, so let's quickly extract this information and delete the rest:
foreach($apiOutput as $id => $result)
{
$points[$id] = array($result['Title'],
$result['Latitude'],
$result['Longitude']);
}
Here are some sample values from our newly defined $points
array:
[0] => Array
(
[0] => Patxi's Chicago Pizza
[1] => 37.445265
[2] => -122.163432
)
[1] => Array
(
[0] => Papa Murphys Pizza Take & Bake
[1] => 37.433243
[2] => -122.129291
)
For each marker we want to put on our map, we need to know its position, and we need some summary text that we can have appear when the user mouses over it. In this case, when visitors mouse over one of our markers, we'll show them the name of the place.
Now that we have all our locality information, we come to the tricky bit -- generating the map HTML and JavaScript. Basically, our map code consists of two distinct sections -- the HTML and CSS (for the map container), and the
HTML and JavaScript. The
includes the container
YGeoPoint
object to define its position, and a YMarker
object to be the marker itself. We then customise the marker through the addLabel
and addAutoExpand
methods (many more are documented here) before placing it on the map using the map object's addOverlay
method. We'll now create a PHP class that takes care of generating all of this JavaScript code, and call it AjaxMap
. Here's a summary of the methods our class will have:
getHeadHTML
for generatingcode
getMapScript
for generatingcode
initMarker
for generating code for each marker
We'll also add some helper methods for customising the map:
setMapType
for choosing between maps, satellite images, and hybridssetMapContainer
for setting the ID of the map containeraddMarker
for adding markers to the map
No comments:
Post a Comment