8. Server side script with PHP

We will use a PHP script to make the routing query and send the result back to the web client.

The following steps are necessary:

  • Retrieve the start and end point coordinates.
  • Find the closest edge to start/end point.
  • Take either the start or end vertex of this edge (for Dijkstra/ A-Star) or the complete edge (Shooting-Star) as start of the route and end respectively.
  • Make the Shortest Path database query.
  • Transform the query result to XML or better GeoJSON and send it back to the web client.

Note

To keep this example as simple as possible with focus on routing queries, this PHP script doesn’t validate request parameters nore does it deal with PHP security issues.

Let’s start with some PHP template and then place this file in a directory, which is accessible by Apache:

<?php

   // Database connection settings
   define("PG_DB"  , "routing");
   define("PG_HOST", "localhost"); 
   define("PG_USER", "postgres");
   define("PG_PORT", "5432"); 
   define("TABLE",   "ways");

   // Retrieve start point
   $start = split(' ',$_REQUEST['startpoint']);
   $startPoint = array($start[0], $start[1]);

   // Retrieve end point
   $end = split(' ',$_REQUEST['finalpoint']);
   $endPoint = array($end[0], $end[1]);
   
?>

8.1. Closest edge

Usually the start and end point, which we retrieved from the client, is not the start or end vertex of an edge. It is more convenient to look for the closest edge than for the closest vertex, because Shooting Star algorithm is “edge-based”. For “vertex-based” algorithms (Dijkstra, A-Star) we can choose arbitrary start or end of the selected edge.

<?php

   // Find the nearest edge
   $startEdge = findNearestEdge($startPoint);
   $endEdge   = findNearestEdge($endPoint);

   // FUNCTION findNearestEdge
   function findNearestEdge($lonlat) {

      // Connect to database
      $con = pg_connect("dbname=".PG_DB." host=".PG_HOST." user=".PG_USER);

      $sql = "SELECT gid, source, target, the_geom, 
		          ST_Distance(the_geom, ST_GeometryFromText(
	                   'POINT(".$lonlat[0]." ".$lonlat[1].")', 4326)) AS dist 
	             FROM ".TABLE."  
	             WHERE the_geom && setsrid(
	                   'BOX3D(".($lonlat[0]-0.1)." 
	                          ".($lonlat[1]-0.1).", 
	                          ".($lonlat[0]+0.1)." 
	                          ".($lonlat[1]+0.1).")'::box3d, 4326) 
	             ORDER BY dist LIMIT 1";

      $query = pg_query($con,$sql);  

      $edge['gid']      = pg_fetch_result($query, 0, 0);  
      $edge['source']   = pg_fetch_result($query, 0, 1);  
      $edge['target']   = pg_fetch_result($query, 0, 2);  
      $edge['the_geom'] = pg_fetch_result($query, 0, 3);  

      // Close database connection
      pg_close($con);

      return $edge;
   }
   
?>

8.2. Routing query

<?php

   // Select the routing algorithm
   switch($_REQUEST['method']) {

      case 'SPD' : // Shortest Path Dijkstra 

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                 length(rt.the_geom) AS length, ".TABLE.".gid 
	              FROM ".TABLE.", 
	                  (SELECT gid, the_geom 
	                      FROM dijkstra_sp_delta(
	                          '".TABLE."',
	                          ".$startEdge['source'].",
	                          ".$endEdge['target'].",
	                          0.1)
	                   ) as rt 
	              WHERE ".TABLE.".gid=rt.gid;";
        break;
        
      case 'SPA' : // Shortest Path A* 

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                   length(rt.the_geom) AS length, ".TABLE.".gid 
	                FROM ".TABLE.", 
	                    (SELECT gid, the_geom 
	                        FROM astar_sp_delta(
	                            '".TABLE."',
	                            ".$startEdge['source'].",
	                            ".$endEdge['target'].",
	                            0.1)
	                     ) as rt 
	                WHERE ".TABLE.".gid=rt.gid;";  
        break;

      case 'SPS' : // Shortest Path Shooting*

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                   length(rt.the_geom) AS length, ".TABLE.".gid 
	                FROM ".TABLE.", 
	                    (SELECT gid, the_geom 
	                        FROM shootingstar_sp(
	                            '".TABLE."',
	                            ".$startEdge['gid'].",
	                            ".$endEdge['gid'].",
	                            0.1, 'length', true, true)
	                     ) as rt 
	                WHERE ".TABLE.".gid=rt.gid;";
        break;   

   } // close switch

   // Connect to database
   $dbcon = pg_connect("dbname=".PG_DB." host=".PG_HOST." user=".PG_USER);

   // Perform database query
   $query = pg_query($dbcon,$sql); 
   
?>

8.3. GeoJSON output

OpenLayers allows to draw lines directly using GeoJSON format, so our script returns a GeoJSON FeatureCollection object:

<?php

   // Return route as GeoJSON
   $geojson = array(
      'type'      => 'FeatureCollection',
      'features'  => array()
   ); 
  
   // Add edges to GeoJSON array
   while($edge=pg_fetch_assoc($query)) {  

      $feature = array(
         'type' => 'Feature',
         'geometry' => json_decode($edge['geojson'], true),
         'crs' => array(
            'type' => 'EPSG',
            'properties' => array('code' => '4326')
         ),
         'properties' => array(
            'id' => $edge['id'],
            'length' => $edge['length']
         )
      );
      
      // Add feature array to feature collection array
      array_push($geojson['features'], $feature);
   }

	
   // Close database connection
   pg_close($dbcon);

   // Return routing result
   header('Content-type: application/json',true);
   echo json_encode($geojson);
   
?>

Table Of Contents

Previous topic

7. Advanced Routing Queries

Next topic

9. GeoExt Browser Client

License

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License.

Creative Commons License