Cómo crear un mapa aportado por los usuarios con PHP y Google Spreadsheets

Pamela Fox, equipo de API de Google Maps
Noviembre de 2007

Objetivo

La Web está llena de comunidades centradas en geografías e intereses: personas que aman museos, catedrales europeas, parques estatales, etc. Así que siempre hay una necesidad de un programador (como tú) de crear un sistema donde los usuarios puedan contribuir con lugares geoetiquetados a un mapa, y eso es exactamente lo que haremos aquí. Al final de este artículo, obtendrá un sistema en el que los usuarios pueden registrarse, acceder y agregar lugares con geoetiquetas. El sistema usará AJAX para el front-end, PHP para secuencias de comandos en el servidor y Google Spreadsheets para almacenamiento. Si estás acostumbrado a usar bases de datos de MySQL para el almacenamiento, podrías modificar fácilmente el código aquí para usar un backend de base de datos de MySQL.

Este artículo se divide en los siguientes pasos:


Configuración de la hoja de cálculo

Utilizaremos Hojas de cálculo de Google para almacenar todos los datos de este sistema. Hay dos tipos de datos que debemos almacenar: información de la cuenta de usuario y lugares agregados por el usuario, por lo que crearemos una hoja de trabajo para cada tipo de datos. Interactuaremos con las hojas de trabajo mediante su feed de lista, que se basa en la primera fila de una hoja de trabajo que contiene las etiquetas de columna y en cada fila subsiguiente que contiene los datos.

Visita docs.google.com y crea una hoja de cálculo nueva. Cambie el nombre de la hoja de cálculo predeterminada a "Usuarios" y cree columnas denominadas "user", "password" y "session". A continuación, agregue otra hoja, cámbiele el nombre a "Ubicaciones" y cree columnas denominadas "user", "status", "lat", "lng" y "date". O bien, si no siente todo ese trabajo manual, descargue esta plantilla y, luego, impórtela a Hojas de cálculo de Google por medio del comando Archivo->Importar.

La información de la cuenta de usuario debe ser privada (solo visible para el propietario de la hoja de cálculo), mientras que los lugares agregados por el usuario se muestran en un mapa visible de forma pública. Afortunadamente, Hojas de cálculo de Google te permite decidir de forma selectiva qué hojas de cálculo pueden ser públicas y cuáles deben permanecer privadas (configuración predeterminada). Para publicar la hoja de cálculo “Ubicaciones”, haga clic en la pestaña “Publicar”, haga clic en “Publicar ahora”, marque la casilla de verificación “Volver a publicar automáticamente” y, a continuación, en el menú desplegable “¿Qué partes?” seleccione “Hoja “Ubicaciones” únicamente”. En la captura de pantalla a continuación, se muestran las opciones correctas:

Cómo trabajar con el marco de trabajo de Gend GData

La API de Hojas de cálculo de Google proporciona una interfaz HTTP para operaciones CRUD, como recuperar filas, insertarlas, actualizarlas y borrarlas. El marco de trabajo de Zend proporciona un wrapper de PHP además de la API (y las otras API de GData) para que no tenga que preocuparse por implementar las operaciones HTTP sin procesar. El marco de trabajo de Zend requiere PHP 5.

Si aún no lo tienes, descarga el marco de trabajo de Zend y súbelo a tu servidor. El marco de trabajo está disponible aquí: http://framework.zend.com/download/gdata.

Debes modificar tu include_path de PHP para incluir la biblioteca Zend. Existen varias formas de hacerlo, según el nivel de derechos de administración que tengas en tu servidor. Una forma es agregar esta línea encima de las declaraciones require en cualquier archivo PHP que use la biblioteca:

ini_set("include_path", ".:/usr/lib/php:/usr/local/lib/php:../../../library/");

Para probarlo, ejecute la demostración de Hojas de cálculo. Para ello, ingrese lo siguiente en la línea de comandos de la carpeta de demostraciones/Zend/Gdata:

php Spreadsheet-ClientLogin.php --user=YourGMailUsername --pass=YourPassword

Si funciona, debería ver una lista con sus hojas de cálculo. Si recibes un error, verifica que la ruta de inclusión esté configurada correctamente y que tengas instalado PHP 5.

Crea funciones globales

Todas las secuencias de comandos PHP que escribiremos para el mapa de la comunidad utilizarán inclusiones, variables y funciones comunes, que colocaremos en un solo archivo.

Al comienzo del archivo, tendremos las declaraciones necesarias para incluir y cargar la biblioteca Zend, tomada del ejemplo Spreadsheets-ClientLogin.php.

Luego, definiremos las constantes que se usarán en todos los archivos: la clave de hoja de cálculo y los dos ID de hoja de trabajo. Para encontrar la información de tu hoja de cálculo, ábrela, haz clic en la pestaña "Publicar" y luego en "Más opciones de publicación". Seleccione "ATOM" en la lista desplegable Formato de archivo y haga clic en "Generar URL". Verás algo como lo siguiente:

http://spreadsheets.google.com/feeds/list/o16162288751915453340.4016005092390554215/od6/public/basic

La clave de la hoja de cálculo es la string alfanumérica larga que aparece después de "/list/", y el ID de la hoja de trabajo es la string larga de 3 caracteres que aparece después. Para encontrar el otro ID de hoja de cálculo, selecciona la otra hoja en el menú desplegable "¿Qué hojas de cálculo?".

Luego, crearemos 3 funciones: setupClient, getWkshtListFeed y printFeed. En setupClient, estableceremos nuestro nombre de usuario y contraseña de Gmail, autenticaremos con ClientLogin y devolveremos un objeto Zend_Gdata_Spreadsheets. En getWkshtListFeed, mostraremos un feed de lista de hojas de cálculo para una clave de hoja de cálculo y un ID de hoja de cálculo determinados, con una consulta opcional de hojas de cálculo (vínculo). La función printFeed se toma del ejemplo de Spreadsheets-ClientLogin.php y puede ser útil para la depuración. Tomará un objeto de feed y lo imprimirá en la pantalla.

A continuación, se muestra el PHP que realiza esta acción (communitymap_globals.php):

<?php
ini_set("include_path", ".:/usr/lib/php:/usr/local/lib/php:../../../library/");
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Spreadsheets');
Zend_Loader::loadClass('Zend_Http_Client');

define("SPREADSHEET_KEY", "o16162288751915453340.4016005092390554215");
define("USER_WORKSHEET_ID", "od6");
define("LOC_WORKSHEET_ID", "od7");
 
function setupClient() {
  $email = "your.name@gmail.com";
  $password = "yourPassword";
  $client = Zend_Gdata_ClientLogin::getHttpClient($email, $password,
          Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME);
  $gdClient = new Zend_Gdata_Spreadsheets($client);
  return $gdClient;
}
 
function getWkshtListFeed($gdClient, $ssKey, $wkshtId, $queryString=null) {
  $query = new Zend_Gdata_Spreadsheets_ListQuery();
  $query->setSpreadsheetKey($ssKey);
  $query->setWorksheetId($wkshtId);
  if ($queryString !== null) {
    $query->setSpreadsheetQuery($queryString);
  }
  $listFeed = $gdClient->getListFeed($query);
  return $listFeed;
}
 
function printFeed($feed)
{
  print "printing feed";
  $i = 0;
  foreach($feed->entries as $entry) {
      if ($entry instanceof Zend_Gdata_Spreadsheets_CellEntry) {
         print $entry->title->text .' '. $entry->content->text . "\n";
      } else if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) {
         print $i .' '. $entry->title->text .' '. $entry->content->text . "\n";
      } else {
         print $i .' '. $entry->title->text . "\n";
      }
      $i++;
  }
}
 
?>

Registrar un usuario nuevo

A fin de registrar un usuario nuevo, necesitaremos una página HTML para el usuario con campos de texto y un botón de enviar, y una secuencia de comandos de backend de PHP para agregar al usuario a la hoja de cálculo.

En la secuencia de comandos PHP, primero incluimos la secuencia de comandos global y, luego, obtenemos los valores de nombre de usuario y contraseña de la variable GET. Luego configuramos un cliente de hojas de cálculo y solicitamos el feed de lista para la hoja de trabajo del usuario con una cadena de consulta para restringir los resultados solo a las filas en las que la columna del nombre de usuario es igual al nombre de usuario que se pasó a la secuencia de comandos. Si no obtenemos filas en el resultado del feed de lista, podemos seguir sabiendo que el nombre de usuario que se pasó es único. Antes de insertar una fila en el feed de lista, creamos un arreglo asociado de los valores de la columna: el nombre de usuario, una encriptación de la contraseña mediante la función sha1 de PHP y un carácter de relleno para la sesión. Luego, llamaremos a insertRow en el cliente de las hojas de cálculo y pasaremos el array asociado, la clave de las hojas de cálculo y el ID de la hoja de cálculo. Si el objeto que se muestra es un ListFeedEntry, el resultado será un mensaje de éxito.

A continuación, se muestra el PHP que realiza esta acción (communitymap_newuser.php):

<?php
 
require_once 'communitymap_globals.php';
 
$username = $_GET['username'];
$password = $_GET['password'];
 
$gdClient = setupClient();
 
$listFeed = getWkshtListFeed($gdClient, SPREADSHEET_KEY, USER_WORKSHEET_ID, ('user='.$username));
$totalResults = $listFeed->totalResults;
if ( $totalResults != "0") {
  // Username already exists
  exit;
}
 
$rowArray["user"] = $username;
$rowArray["password"] = sha1($password);
$rowArray["session"] = "a";
 
$entry = $gdClient->insertRow($rowArray, SPREADSHEET_KEY, USER_WORKSHEET_ID);
if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) {
  echo "Success!";
}
?>

En la página de registro, podemos incluir la API de Google Maps, de modo que podamos utilizar su función de wrapper XMLHttpRequest llamada GDownloadUrl. Cuando el usuario haga clic en el botón Enviar, obtendremos el nombre de usuario y la contraseña de los campos de texto, crearemos una cadena de parámetros a partir de sus valores y llamaremos a GDownloadUrl en los parámetros y la URL de la secuencia de comandos. Debido a que enviamos información sensible, utilizamos la versión HTTP POST de GDownloadUrl (enviando los parámetros como el tercer argumento en lugar de anexarlos a la URL). En la función de devolución de llamada, verificaremos si la respuesta se realizó correctamente y le enviaremos un mensaje adecuado al usuario.

A continuación, se muestran una captura de pantalla y el código de una página de registro de muestra (communitymap_register.htm):


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title> Community Map - Register/Login </title>

  <script src="http://maps.google.com/maps?file=api&v=2&key=abcdef"
      type="text/javascript"></script>
  <script type="text/javascript">

  function register() {
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value;
    var url = "communitymap_newuser.php?";
    var params = "username=" + username + "&password=" + password;
    GDownloadUrl(url, function(data, responseCode) {
      if (data.length > 1) {
        document.getElementById("message").innerHTML = "Successfully registered." + 
          "<a href='communitymap_login.htm'>Proceed to Login</a>.";
      } else {
        document.getElementById("message").innerHTML = "Username already exists. Try again.";
      }
    }, params);
  }

  </script>

  </head>
  <body>
  <h1>Register for Community Map</h1>
  <input type="text" id="username">
  <input type="password" id="password">

  <input type="button" onclick="register()" value="Register">
  <div id="message"></div>
  </body>
</html>

Accede a un usuario

Para permitir que los usuarios accedan a nuestro sistema, la página HTML nos solicitará su nombre de usuario y contraseña, y una secuencia de comandos PHP para verificar la información de acceso, crear un ID de sesión y pasarlo a la página de acceso para configurar una cookie. El usuario permanecerá conectado a través de la cookie de sesión en las páginas subsiguientes.

En la secuencia de comandos PHP, primero incluimos la secuencia de comandos global y, luego, obtenemos los valores de nombre de usuario y contraseña de la variable GET. Luego configuramos un cliente de hojas de cálculo y solicitamos el feed de lista para la hoja de trabajo del usuario con una cadena de consulta para restringir los resultados solo a las filas en las que la columna del nombre de usuario es igual al nombre de usuario que se pasó a la secuencia de comandos.

En la fila que se muestra, verificaremos que el hash de la contraseña que se pasó coincida con el hash almacenado en la hoja de cálculo. Si es así, crearemos un ID de sesión con las funciones md5, uniqid y rand. Luego, actualizaremos la fila en la hoja de cálculo con la sesión y la colocaremos en la pantalla si la actualización de la fila se realiza correctamente.

El PHP que hace eso se muestra a continuación (communitymap_loginuser.php):

<?php
 
require_once 'communitymap_globals.php';
 
$username = $_POST['username'];
$password = $_POST['password'];
 
$gdClient = setupClient();
 
$listFeed = getWkshtListFeed($gdClient, SPREADSHEET_KEY, USER_WORKSHEET_ID, ('user='.$username));
 
$password_hash = sha1($password);
$row = $listFeed->entries[0];
$rowData = $row->getCustom();
foreach($rowData as $customEntry) {
  if ($customEntry->getColumnName()=="password" && $customEntry->getText()==$password_hash) {
    $updatedRowArray["user"] = $username;
    $updatedRowArray["password"] = sha1($password);
    $updatedRowArray["session"] = md5(uniqid(rand(), true));
    $updatedRow = $gdClient->updateRow($row, $updatedRowArray); 
    if ($updatedRow instanceof Zend_Gdata_Spreadsheets_ListEntry) {
      echo $updatedRowArray["session"];
    }
  }
}
?>

En la página de acceso, podemos volver a incluir la API de Google Maps, de modo que podamos utilizar su función wrapper XMLHttpRequest llamada GDownloadUrl. Cuando el usuario haga clic en el botón Enviar, obtendremos el nombre de usuario y la contraseña de los campos de texto, crearemos la URL de la secuencia de comandos con los parámetros de consulta y llamaremos a GDownloadUrl en la URL de la secuencia de comandos. En la función de devolución de llamada, estableceremos una cookie con el ID de sesión que la secuencia de comandos mostrará o mostrará un mensaje de error si no se muestra ninguno. La función setCookie proviene de un cookie.js que se basa en el tutorial de w3c sobre JavaScript: http://www.w3schools.com/js/js_cookies.asp.

A continuación, se muestran una captura de pantalla y el código de una página de acceso de muestra (communitymap_login.htm):


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>

  <title>Community Map - Login</title>
      <script src="http://maps.google.com/maps?file=api&v=2&key=abcdef"
      type="text/javascript"></script>
  <script src="cookies.js" type="text/javascript"></script>
  <script type="text/javascript">

  function login() {
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value;
    var url = "communitymap_loginuser.php?username=" + username + "&password=" + password;
    GDownloadUrl(url, function(data, responseCode) {
      if (data.length > 1) {
        setCookie("session", data, 5);
      } else {
        document.getElementById("nessage").innerHTML = "Error. Try again.";
      }
    });
  }

  </script>
  </head>
  <body>

  <h1>Login for Community Map</h1>

  <input type="text" id="username">
  <input type="password" id="password">
  <input type="button" onclick="login()" value="Login">
  <div id="message"></div>
  </body>
</html>

Permitir que los usuarios agreguen lugares del mapa

A fin de que un usuario pueda agregar lugares a nuestro mapa, queremos que la página HTML orientada al usuario le proporcione información sobre la ubicación y dos secuencias de comandos PHP: una para verificar que haya accedido mediante la cookie que establecimos y otra para agregar la ubicación a la hoja de trabajo de ubicaciones.

En la primera secuencia de comandos de PHP, que verifica si un usuario accedió, primero incluimos la secuencia de comandos global y, luego, obtenemos el valor de la sesión de la variable GET. Luego configuramos un cliente de hojas de cálculo y solicitamos el feed de lista para la hoja de trabajo del usuario con una cadena de consulta para restringir los resultados solo a aquellas filas en las que la columna de sesión sea igual al valor de sesión que se pasó a la secuencia de comandos. A continuación, iteramos a través de las entradas personalizadas de ese feed (las que corresponden a los encabezados de las columnas) e imprimimos el nombre de usuario correspondiente a esa sesión, si existe uno.

El PHP que hace eso se muestra abajo (communitymap_checksession.php):

<?php

require_once 'communitymap_globals.php';

$session = $_GET['session'];

$gdClient = setupClient();

$listFeed = getWkshtListFeed($gdClient, SPREADSHEET_KEY, USER_WORKSHEET_ID, ('session='.$session));

if ( count($listFeed->entries) > 0) {
  $row = $listFeed->entries[0];
  $rowData = $row->getCustom();
  foreach($rowData as $customEntry) {
    if ($customEntry->getColumnName()=="user") {
      echo $customEntry->getText();
    }
  }
}
?>

En la segunda secuencia de comandos de PHP que permite que un usuario agregue una ubicación, primero replicamos el código decommunitymap_checksession.php para asegurarnos de que el usuario haya accedido y sea válido. Una vez que obtenemos un nombre de usuario válido de la hoja de usuarios, obtenemos los valores de lugar, latitud y longitud de la variable GET. Colocamos todos esos valores en un arreglo asociativo y también agregamos un valor “date” con la función date() de PHP, para que sepamos cuando el usuario agregó el lugar. Pasamos ese arreglo asociado, la constante de clave de las hojas de cálculo y la constante de ID de la hoja de cálculo de ubicaciones a la función insertRow. Luego, se muestra “Finalizado” si se agrega una fila para la ubicación nueva a la hoja de cálculo. Si recibe un mensaje de error en este paso, probablemente se deba a una discrepancia de nombres de encabezado de columna. Las claves del array asociado deben coincidir con los encabezados de columna de la hoja de cálculo que se especifican en la clave y el ID de la hoja de cálculo.

El PHP que hace eso se muestra a continuación (communitymap_addlocation.php):

<?php

require_once 'communitymap_globals.php';

$session = $_GET['session'];

$gdClient = setupClient();

$listFeed = getWkshtListFeed($gdClient, SPREADSHEET_KEY, USER_WORKSHEET_ID, ('session='.$session));

if ( count($listFeed->entries) > 0) {
  $row = $listFeed->entries[0];
  $rowData = $row->getCustom();
  foreach($rowData as $customEntry) {
    if ($customEntry->getColumnName()=="user") {
      $user = $customEntry->getText();
    }
  }

  $place = $_GET['place'];
  $lat = $_GET['lat'];
  $lng = $_GET['lng'];
  $rowArray["user"] = $user;
  $rowArray["place"] = $place;
  $rowArray["lat"] = $lat;
  $rowArray["lng"] = $lng;
  $rowArray["date"] = date("F j, Y, g:i a");
  $entry = $gdClient->insertRow($rowArray, SPREADSHEET_KEY, LOC_WORKSHEET_ID);
  if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) {
    echo "Success!\n";
  }
}

?>

En la página Agregar ubicación, podemos volver a incluir la API de Google Maps, de modo que podamos utilizar GDownloadUrl y crear un mapa. Después de que se carga la página, usamos la función getCookie del archivo cookies.js para recuperar el valor de la sesión. Si la string de la sesión es nula o vacía, se mostrará un mensaje de error. Si no es así, se llama a GDownloadUrl en map.checksession.php y se envía la sesión. Si el nombre de usuario se devuelve correctamente, mostraremos un mensaje de bienvenida al usuario, revelaremos el formulario para agregar una ubicación y cargaremos el mapa. El formulario consta de un campo de texto de dirección, un mapa y campos de texto para el nombre del lugar, la latitud y la longitud. Si el usuario aún no conoce la latitud o la longitud de la ubicación, puede geocodificarla ingresando su dirección en el formulario y presionando "enviar". Con esto se enviará una llamada al GClientGeocoder de la API de Google Maps, que colocará un marcador en el mapa si encuentra la dirección y completará automáticamente los campos de texto de latitud y longitud.

Cuando el usuario esté satisfecho, puede presionar el botón “Agregar ubicación”. Luego, en JavaScript, obtendremos los valores para user, place, lat y lng, y los enviaremos a la secuencia de comandos Communitymap_addlocation.php con GDownloadUrl.

Si la secuencia de comandos muestra el error, se mostrará un mensaje de éxito en la pantalla.

A continuación, se muestra una captura de pantalla y un código de una página de ejemplo para agregar la ubicación (communitymap_addlocation.htm):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Community Map - Add a Place!</title>

    <script src="http://maps.google.com/maps?file=api&v=2.x&key=abcdef" type="text/javascript"></script>
    <script src="cookies.js" type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[

    var map = null;
    var geocoder = null; 
    var session = null;

    function load() {
      session = getCookie('session');
      if (session != null && session != "") {
        url = "communitymap_checksession.php?session=" + session;
        GDownloadUrl(url, function(data, responseCode) {
          if (data.length > 0) {
            document.getElementById("message").innerHTML = "Welcome " + data;
            document.getElementById("content").style.display = "block";
            map = new GMap2(document.getElementById("map"));
            map.setCenter(new GLatLng(37.4419, -122.1419), 13);
            geocoder = new GClientGeocoder();
          }
        });
      } else {
        document.getElementById("message").innerHTML = "Error: Not logged in.";
      }
    }

    function addLocation() {
      var place = document.getElementById("place").value;
      var lat = document.getElementById("lat").value;
      var lng = document.getElementById("lng").value;

      var url = "communitymap_addlocation.php?session=" + session + "&place=" + place +
                "&lat=" + lat + "&lng=" + lng;
      GDownloadUrl(url, function(data, responseCode) {
        GLog.write(data);
        if (data.length > 0) {
          document.getElementById("message").innerHTML = "Location added.";
        }
      });
    }

    function showAddress(address) {
      if (geocoder) {
        geocoder.getLatLng(
          address,
          function(point) {
            if (!point) {
              alert(address + " not found");
            } else {
              map.setCenter(point, 13);
              var marker = new GMarker(point, {draggable:true});
              document.getElementById("lat").value = marker.getPoint().lat().toFixed(6);
              document.getElementById("lng").value = marker.getPoint().lng().toFixed(6);

              map.addOverlay(marker);
              GEvent.addListener(marker, "dragend", function() {
                document.getElementById("lat").value = marker.getPoint().lat().toFixed(6);
                document.getElementById("lng").value = marker.getPoint().lng().toFixed(6);
	      });
            }
          }
        );
      }
    }
    //]]>

    </script>

  </head>

  <body onload="load()" onunload="GUnload()">
   <div id="message"></div>
   <div id="content" style="display:none">

   <form action="#" onsubmit="showAddress(this.address.value); return false">
        <p>
        <input type="text" size="60" name="address" value="1600 Amphitheatre Pky, Mountain View, CA" />
        <input type="submit" value="Geocode!" />

    </form>
      </p>

      <div id="map" style="width: 500px; height: 300px"></div>
 
 	Place name: <input type="text" size="20" id="place" value="" />
	<br/>
 	Lat: <input type="text" size="20" id="lat" value="" />
	<br/>

 	Lng: <input type="text" size="20" id="lng" value="" />

        <br/>
	<input type="button" onclick="addLocation()" value="Add a location" />
    </form>
    </div>

  </body>
</html>

Creación del mapa

Debido a que hiciste pública la hoja de cálculo de ubicaciones en el primer paso, no se requiere programación en el servidor para crear un mapa de ellas. De hecho, no es necesario programar nada. Utiliza este Asistente de hojas de cálculo -> Mapa a fin de generar todo el código necesario para el mapa. El asistente descarga las entradas de la hoja de trabajo en la página al anexar una etiqueta de secuencia de comandos que apunta a la salida JSON para el feed y especifica una función de devolución de llamada a la que se llama una vez que el JSON se ha descargado. Obtenga más información aquí.

El código HTML de muestra para hacerlo está disponible aquí: mainmap.htm. A continuación, se muestra una captura de pantalla:

Conclusión

Esperamos que tu propio sistema de mapas aportado por los usuarios se ejecute en tu servidor. En este artículo, se proporciona el código básico necesario para los aspectos esenciales de este sistema. Sin embargo, ahora que está familiarizado con la biblioteca de Zend Spreadsheets, debería poder extender el sistema a fin de satisfacer sus necesidades particulares. Si encontraste errores durante el proceso, recuerda que puedes usar el comando echo en PHP o el elemento GLog.write() de la API de Google Maps en JavaScript para la depuración. Además, siempre puedes realizar publicaciones en los foros de desarrolladores API de Maps o API de Hojas de cálculo para obtener ayuda adicional.