Consuming MapPoint Web Service in PHP

 

IMPORTANT: MapPoint Web Service was retired on November 18, 2011. Please see Bing Maps for a list of current Bing Maps APIs.

Francois Joffre
Microsoft Corporation

February 2005

Applies to:
Microsoft MapPoint Web Service

Summary: Learn how to consume MapPoint Web Service by using PHP and the NuSoap toolkit. This article is accompanied by sample code that illustrates how to implement a simple proximity-locator application.

Contents

Introduction

About the Sample Application

Setting Up the Application

Calling the MapPoint Web Service FindAddress Method

Using MapPoint Web Service with the Next Version of NuSOAP

Conclusion

Introduction

MapPoint Web Service is a subscription-based Web service that provides maps, driving directions, distance calculations, and other location-based services. Because MapPoint Web Service uses SOAP and Web Service Description Language (WSDL), you can integrate MapPoint Web Service functions into almost any Internet-enabled application. This article describes how to consume MapPoint Web Service functions by using PHP: Hypertext Preprocessor (PHP) and the NuSOAP toolkit, and provides a preview of the next version of NuSOAP.

We used NuSOAP because it supports Digest Authentication and is often used by developers who are consuming Web services in PHP. Although the latest version of PHP (5.0.x) includes a built-in SOAP extension, it is not well documented and doesn't appear to support Digest Authentication, which is required to access MapPoint Web Service.

To illustrate the concepts in this article, we'll implement a simple proximity-locator application. This article assumes that you are already familiar with MapPoint Web Service and the MapPoint Web Service API. For more information about MapPoint Web Service and MapPoint technologies in general, see the MapPoint Developer Center on MSDN.

About the Sample Application

The sample application that accompanies this article prompts the user for an address and then performs a search for nearby locations that are included in the Fourth Coffee Company data source, a public MapPoint Web Service data source that contains sample data. The closest locations are displayed along with an overview map, in addition to links to a map page for specific information or driving directions to a given location.

The application consists of several types of files:

  • General utilities—The file lib/misc.php contains general functions that help make building the application easier—for example, a function that builds URL query string parameters based on an array of parameters.
  • MapPoint configuration—The file lib/constants.php defines a number of constants that are used throughout the code. The file also contains the MapPoint Web Service user name and password that the application uses, and specifies whether to use the MapPoint Web Service staging or production environment. You can also use this file to set proxy properties if your development environment requires that you use a proxy. Note that HTTP proxy support with Digest Authentication may not work in NuSOAP 0.6.7 and, therefore, you may not be able to run the sample application if you use an HTTP proxy. For more information, see "Using MapPoint Web Service with the Next Version of NuSOAP" later in this article.
  • MapPoint Web Service utilities—These files contain helper code for making calls to MapPoint Web Service. They provide functions that initialize MapPoint Web Service structures for a particular operation, and then call the corresponding method of MapPoint Web Service. There is one file for each type of MapPoint Web Service operation that is included in the application: geocoding addresses (geocode.php), proximity searching (find.php), rendering maps (render.php), and calculating driving directions (route.php).
  • Locator pages—These files define the Web pages that correspond to each state of the application and use the MapPoint Web Service utilities to make calls to MapPoint Web Service.
    • prxinput.php is the entry page that prompts the user for address information and then geocodes the address (optionally displaying approximate matches or an error message if an address cannot be matched with a precise location).
    • prxresults.php is the proximity results page that displays the locations closest to the user's address.
    • prxmap.php is the map page that displays a navigable map for a specific location.
    • prxdriveresults.php displays route results from the user's address to a given location.
    • mapnav.php displays a map and its associated navigation components. This code is in a separate file because it is used in multiple places (such as prxresults.php and prxmap.php).
  • Other files—The files header.php, footer.php, and locator.css define the overall look and feel of the application. Also note that header.php includes all of the files necessary for the application, so it is required for application consistency. The file index.php redirects the application to the address entry page (prxinput.php).

Setting Up the Application

This section describes the prerequisites you'll need and provides step-by-step instructions for installing and running the sample application.

Prerequisites

To run the sample application, you'll need the following components:

  • An active MapPoint Web Service account—MapPoint Web Service is a subscription-based system. To access the service, you need a valid account. You can sign up for a 45-day evaluation account at this page on Microsoft.com.

  • PHP 4.3.x—The sample application was written in PHP 4.3.5, running on an Apache server on a Microsoft Windows XP–based system; however, the sample application may work with other versions of PHP running on different configurations. You can download PHP from the PHP Web site.

  • NuSOAP 0.6.7—NuSOAP is easy to install because it is bundled as a unique PHP file that you include in another PHP application to gain access to its features. You can download the latest version of NuSOAP from this page on the SourceForge Web site.

    Note  NuSOAP is actively under development. The current development version offers new features that have been requested by users, including some that are necessary to implement certain features of MapPoint Web Service. For more information, see "Using MapPoint Web Service with the Next Version of NuSOAP" later in this article.

In addition to the prerequisites listed in this section, you may also want to download or view the MapPoint Web Service Software Development Kit (SDK), version 3.5. The SDK contains all documentation and reference material for MapPoint Web Service, in addition to example code in C# and Microsoft Visual Basic. Although the contents of the SDK are not required to compile and run your application, you will find it immensely helpful to have this reference material installed on your development computer. To download the SDK or view it online, visit the MapPoint Web Service Developer Center on MSDN.

Installing and Running the Application

Use the following procedure to install the sample application.

To install and run the application

  1. Download the sample from this page in the Microsoft Download Center. By default, the sample application will be installed in the following location:

    C:\Program Files\MapPoint Web Service Samples\phplocator

  2. Copy the phplocator subfolder and its contents, and then paste it under the document root folder for your Web server. The phplocator directory will contain a subfolder named lib.

  3. In the lib folder, open the file constants.php, and set the constants MPUSER and MPPWD to the user name and password for your MapPoint Web Service account. This file also specifies whether to use the MapPoint Web Service staging or production environment. (If you have a MapPoint Web Service evaluation account, you must use the staging environment.) You can also set proxy properties if your development environment requires that you use one.

  4. Copy the file nusoap.php from the NuSOAP package that you downloaded earlier, and paste it into the lib folder.

  5. To run the application, in the address bar of your Web browser, type the path to the file prxinput.php. For example, if your Web server is running on port 80 of your local computer, you can access the application by using the following URL:

    http://localhost/phplocator/prxinput.php
    

Calling the MapPoint Web Service FindAddress Method

The section illustrates how to call MapPoint Web Service methods from NuSOAP, using the FindAddress method as an example. We first describe how to geocode an address by calling FindAddress and then explain how to parse the results contained in the FindResults object that is returned. For examples of how to call other MapPoint Web Service methods from NuSOAP, see the sample code that accompanies this article.

First, we create a NuSOAP instance of MapPoint Web Service.

//Point to the local copy of NuSOAP.
require('lib/nusoap.php'); 
//MapPoint Web Service user name goes here.
$mapPointUserName = "";
//MapPoint Web Service password goes here.
$mapPointPassword = "";
//A MapPoint Web Service evaluation account includes
//access to the MapPoint Web Service staging environment only.
$mapPointWsdl = "http://staging.mappoint.net/standard-30/mappoint.wsdl";
$client = new soapclient($mapPointWsdl, true);
$err = $client->getError();
if ($err)
{
die('An error occurred while the WSDL was being accessed: '.$err);
}
$client->setCredentials($mapPointUserName,$mapPointPassword,'digest');

Before calling the FindAddress method, we need to create a FindAddressSpecification object, which contains the information that will be passed to FindAddress. This object is defined as an array that contains a DataSourceName property (a string); an InputAddress property (an Address object); and an Options property (a FindOptions object). We'll first define the Address and FindOptions objects. (We'll set the DataSourceName property later when we create the FindAddressSpecification object by using the public MapPoint Web Service data source for North America.)

Here is the code that defines the Address object.

$address = array(
   'AddressLine' => "1 Microsoft Way",
   'PrimaryCity' => "Redmond",
   //SecondaryCity is not required for U.S. addresses.
   'Subdivision' => "WA",
   'PostalCode' => "98052",
   'CountryRegion' => 'USA'
);

Here is the code that defines the FindOptions object. For more information about FindOptions, see FindOptions Class in the MapPoint Web Service SDK.

//Define the FindRange object, which determines the first result we
//want returned and the number of
//results to return.
$findRange = array(
   'StartIndex' => 0,
   'Count' => 100
);
//Define a FindResultMask object to specify which
//properties should be returned along with the results.
$findResultMask = 'AddressFlag LatLongFlag';
//Define the FindOptions object.
$findOptions = array(
   'Range' => $findRange,
   'SearchContext' => 244,
   'ResultMask' => $findResultMask,
   'ThresholdScore' => 0.85
);

Now that we've defined everything we need, we can create the FindAddressSpecification object and call the FindAddress method.

$findAddressSpecification = array(
   'DataSourceName' => 'MapPoint.NA', 
   'InputAddress' => $address,
   'Options' => $findOptions
);
$findAddress = array('specification' => $findAddressSpecification);
//Call the FindAddress method.
$res=$client->call('FindAddress', array('parameters' => $findAddress));
//Make sure no fault or error has occurred.
if ($client->fault)
{
die('Fault occurred using Web Service:\n'.print_r($res,true));
}
if ($client->getError())
{
   die('An error occurred while using MapPoint Web Service:\n'.$client->getError());
}
//If the code executes to this line, $res 
//contains a FindResults object
//returned by MapPoint Web Service.

Parsing the Results

If you run the code in the previous section, you'll get the following structure:

[NumberFound] => 1
[StartIndex] => 0
[Results] => Array
(
   [FindResult] => Array
   (
      [Score] => 0.95
      [FoundLocation] => Array
      (
         [LatLong] => Array
         (
            [Latitude] => 47.644681234719286
            [Longitude] => -122.13021639802614
         )
         [Address] => Array
         (
            [AddressLine] => 1 Microsoft Way
            [PrimaryCity] => Redmond
            [SecondaryCity] => 
            [Subdivision] => WA
            [PostalCode] => 98052
            [CountryRegion] => United States
            [FormattedAddress] => 1 Microsoft Way, Redmond, WA 98052
         )
         [DataSourceName] => MapPoint.NA
      )
   )
)
[TopScore] => 0.95

Based on this information, we can use the following code to display the latitude and longitude of the geocoded location.

$lat=$res['Results']['FindResult']['FoundLocation']['LatLong']['Latitude'];
$lon=$res['Results']['FindResult']['FoundLocation']['LatLong']['Longitude'];
echo("The latitude/longitude for the address is: $lat/$lon");

Working with Multiple Results

NuSOAP has an unusual way of dealing with SOAP array structures: it uses different formats depending on whether one element or multiple elements are returned.

For example, in the previous section, if we only specify a city (Redmond) instead of providing a complete address, MapPoint Web Service returns multiple matches (because there is more than one city named Redmond in the United States). With this modification, the Results structure is similar to the following code. (To reduce the size of the example, only the first two locations are shown. Six results are actually returned.)

 [Results] => Array
(
   [0] => Array
   (
      [Score] => 0.95
      [FoundLocation] => Array
      (
         [LatLong] => Array
         (
            [Latitude] => 47.67857946357006
            [Longitude] => -122.13084477542978
         )
         [Address] => Array
         (
            [AddressLine] => 
            [PrimaryCity] => Redmond
            [SecondaryCity] => 
            [Subdivision] => Washington
            [PostalCode] => 
            [CountryRegion] => United States
            [FormattedAddress] => Redmond, Washington
         )
         [DataSourceName] => MapPoint.NA
      )
   )
   [1] => Array
   (
      [Score] => 0.95
      [FoundLocation] => Array
      (
         [LatLong] => Array
         (
            [Latitude] => 44.272599766011069
            [Longitude] => -121.17564282000349
         )
         [Address] => Array
         (
            [AddressLine] => 
            [PrimaryCity] => Redmond
            [SecondaryCity] => 
            [Subdivision] => Oregon
            [PostalCode] => 
            [CountryRegion] => United States
            [FormattedAddress] => Redmond, Oregon
         )
         [DataSourceName] => MapPoint.NA
      )
   )
)

Notice that there is no FindResult level in the structure that was returned. Instead, numbered array indexes are present. Therefore, to get the latitude and longitude for the first location, we need the following code.

$lat=$res['Results'][0]['FoundLocation']['LatLong']['Latitude'];
$lon=$res['Results'][0]['FoundLocation']['LatLong']['Longitude'];
echo("The geocoded lat/long of the first match is: $lat/$lon");

Normally, separate logic would be required depending on the number of results that are returned, but the sample code associated with this article provides a workaround. If only one result is returned, we re-index the result immediately after it is retrieved and set its index to 0. That way, no special logic is required to deal with results later in the code.

Note that in the sample code we don't do this for the FindResults object returned by the FindAddress method. If only one result is returned, the application displays the proximity results page. If multiple results are returned, the application displays a list of matches for the user to choose from. However, we do this for the FindResults object that is returned by the FindNearby method and we use similar logic for the results of a route. In each case, this workaround is outlined by comments in the code.

Using MapPoint Web Service with the Next Version of NuSOAP

NuSOAP is a work in progress. As such, some features that are required for accessing MapPoint Web Service are either not yet implemented or need improvement. The version we used for this article was the latest official release at the time the article was published. However, a development version of NuSOAP is available that contains additional features and fixes some previous problems. You can get this version from the NuSOAP CVS tree on the SourceForge Web site.

In the development version, arrays of results are formatted differently than they are in the current version. The development version also includes improved proxy support and support for untyped elements.

Important  The sample application may not work with the development version of NuSOAP. You can modify your code to accommodate changes in the development version, as described later in this section, but there may be further changes to the development version that will cause the sample application to break. This version is also likely to contain bugs because it has not been officially released.

Arrays of Results

We described earlier how NuSOAP formats arrays of results differently depending whether there is one result or multiple results. The new version of NuSOAP doesn't correct this problem; however, when multiple results are returned, they are formatted differently: the FindResult level is used and the zero-indexed level is added into it. This means that when there are multiple results, the depth of the resulting structure is increased by one. If there is only one result, the structure is the same as with the current version. The following code illustrates how the new version of NuSOAP we tested (version 0.6.8, release 1.81) returns multiple results when only the city name is provided in the FindAddressSpecification object.

[Results] => Array
(
   [FindResult] => Array
   (
      [0] => Array
      (
         [Score] => 0.95
         [FoundLocation] => Array
         (
            [LatLong] => Array
            (
               [Latitude] => 47.67857946357006
               [Longitude] => -122.13084477542978
            )
            [Address] => Array
            (
               [AddressLine] => 
               [PrimaryCity] => Redmond
               [SecondaryCity] => 
               [Subdivision] => Washington
               [PostalCode] => 
               [CountryRegion] => United States
               [FormattedAddress] => Redmond, Washington
            )
            [DataSourceName] => MapPoint.NA
         )
      )
      [1] => Array
      (
         [Score] => 0.95
         [FoundLocation] => Array
         (
            [LatLong] => Array
            (
               [Latitude] => 44.272599766011069
               [Longitude] => -121.17564282000349
            )
            [Address] => Array
            (
               [AddressLine] => 
               [PrimaryCity] => Redmond
               [SecondaryCity] => 
               [Subdivision] => Oregon
               [PostalCode] => 
               [CountryRegion] => United States
               [FormattedAddress] => Redmond, Oregon
            )
            [DataSourceName] => MapPoint.NA
         )
      )
   )
)

If you want to use the new version of NuSOAP, you'll need to modify your code to accommodate this change.

Better Proxy Support

The sample application contains code to allow the use of an HTTP proxy to access MapPoint Web Service. However, this code doesn't appear to work with all types of proxies because of a Digest Authentication issue. This issue has been resolved in the new version.

Support for Untyped Elements

Support for untyped elements has been added in the development version. With support for untyped elements, you can specify a type for an element for which no type is defined in the WSDL. This feature is particularly useful for setting filter options for calls to the FindNearby method. For example, untyped elements are defined by both the WhereClause and Expression elements of the FindFilter element of a FindNearbySpecification element. Thus, you cannot use these with the current version of NuSOAP. Because setting up these elements might not be obvious, the following code example illustrates how to implement a WhereClause by using the newer version of NuSOAP.

Suppose we want to search only for coffee shop locations that are open.

$pairs=array();
$pairs[0]=array(
   'Name' => "StoreOpen",
   'Value' => new soapval('Value', 'string', 'Y', false,
'http://www.w3.org/2001/XMLSchema')
);
$pairs[1]=array(
   'Name' => "StoreType",
   'Value' => new soapval('Value', 'string', 'Coffee Shop', false,
'http://www.w3.org/2001/XMLSchema')
);
$whereClause = array('SearchProperties' => array('Property' => $pairs));
//Then your $findFilter would become:
$findFilter = array(
   'EntityTypeName' => 'FourthCoffeeShops',
   'PropertyNames' => $props,
   'WhereClause' => $whereClause
);

Note that the type of the object is defined by using the soapval method of NuSOAP.

You can add this code to the file find.php if you want to use the new version of NuSOAP. Remember that you'll also have to change the way in which you parse the results that are returned, as explained earlier.

This code is easily adaptable if you want to create an Expression query instead of a WhereClause.

Conclusion

Implementing location-enabled applications in PHP is easier than it used to be, thanks to the NuSOAP toolkit. In this article, we've seen how to use it to make basic calls to MapPoint Web Service. You can use this sample code as a template for implementing your own locator application.