PHP और Google स्प्रेडशीट के साथ उपयोगकर्ता के योगदान से बनाया गया मैप बनाना

पामेला फ़ॉक्स, Google Maps API टीम
नवंबर 2007

मकसद

वेब, भूगोल और रुचियों से संबंधित समुदायों से भरा हुआ है: संग्रहालय, यूरोपीय कैथेड्रल, राज्य उद्यानों, वगैरह को पसंद करने वाले लोग, इसलिए हमेशा एक डेवलपर (जैसे आप!) की आवश्यकता होती है, ताकि वह ऐसा सिस्टम बना सके जहां उपयोगकर्ता मैप पर जियोटैग किए गए स्थानों का योगदान कर सकें और यहां हम यही करें. इस लेख के अंत में, आपको एक ऐसा सिस्टम मिलेगा जिस पर उपयोगकर्ता रजिस्टर कर सकेंगे, लॉगिन कर सकेंगे, और जियोटैग की गई जगहें जोड़ सकेंगे. सिस्टम फ़्रंट-एंड के लिए AJAX, सर्वर-साइड स्क्रिप्टिंग के लिए PHP, और स्टोरेज के लिए Google स्प्रेडशीट का इस्तेमाल करेगा. अगर आप स्टोरेज के लिए MySQL डेटाबेस का इस्तेमाल करने के आदी हो गए हैं, तो इसके बजाय MySQL डेटाबेस बैकएंड का इस्तेमाल करने के लिए आसानी से कोड में बदलाव कर सकते हैं.

इस लेख को इन चरणों में बांटा गया है:


स्प्रेडशीट सेट अप करना

इस सिस्टम का पूरा डेटा सेव करने के लिए, हम Google स्प्रेडशीट का इस्तेमाल करेंगे. हमें दो तरह के डेटा को स्टोर करने की ज़रूरत होती है: उपयोगकर्ता खाते की जानकारी और उपयोगकर्ता की जोड़ी गई जगहें. इसलिए, हम हर तरह के डेटा के लिए एक वर्कशीट बनाएंगे. हम वर्कशीट के साथ उनके सूची फ़ीड का इस्तेमाल करेंगे. इसमें वे पहली लाइन पर निर्भर करती हैं जिसमें कॉलम लेबल होते हैं. इसके बाद, हर लाइन में डेटा मौजूद होता है.

docs.google.com पर जाएं और एक नई स्प्रेडशीट बनाएं. डिफ़ॉल्ट वर्कशीट का नाम बदलकर "उपयोगकर्ता" करें और "उपयोगकर्ता", "पासवर्ड", और "सेशन" नाम के कॉलम बनाएं. इसके बाद, एक और शीट जोड़ें, उसका नाम बदलकर "जगहें" करें, और "उपयोगकर्ता", "स्थिति", "लाट", "एलएनजी", और "तारीख" नाम के कॉलम बनाएं. या अगर आपको लगता है कि ये सभी काम मैन्युअल तरीके से किए जा रहे हैं, तो यह टेम्प्लेट डाउनलोड करें और उसे फ़ाइल->इंपोर्ट करने के निर्देश की मदद से Google स्प्रेडशीट में इंपोर्ट करें.

उपयोगकर्ता खाते की जानकारी को निजी (केवल स्प्रैडशीट स्वामी को दिखाई देने वाली) बनाए रखने की आवश्यकता होती है, जबकि उपयोगकर्ता की ओर से जोड़ी गई जगहें सार्वजनिक रूप से दिखाई देने वाले मैप पर दिखाई जाती हैं. अच्छी बात यह है कि Google स्प्रेडशीट की मदद से आप चुन सकते हैं कि किसी स्प्रेडशीट में कौनसी वर्कशीट सार्वजनिक हो और कौनसी निजी (डिफ़ॉल्ट) होनी चाहिए. "स्थान" वर्कशीट को प्रकाशित करने के लिए, "प्रकाशित करें" टैब पर क्लिक करें, "अभी प्रकाशित करें" पर क्लिक करें, "अपने-आप फिर से प्रकाशित करें" चेकबॉक्स चुनें और "क्या हिस्से हैं?" ड्रॉप-डाउन में, "सिर्फ़ शीट 'जगहें" चुनें. सही विकल्प, नीचे दिए गए स्क्रीनशॉट में दिखाए गए हैं:

Zend GData फ़्रेमवर्क के साथ काम करना

Google Spreadsheets API CRUD कार्रवाइयों के लिए एचटीटीपी इंटरफ़ेस देती है, जैसे कि पंक्तियां वापस पाना, पंक्तियां जोड़ना, पंक्तियां अपडेट करना. Zend फ़्रेमवर्क, API (और दूसरे GData API) के ऊपर एक PHP रैपर उपलब्ध कराता है, ताकि आपको कच्चे HTTP ऑपरेशन को लागू करने की चिंता न करनी पड़े. Zend फ़्रेमवर्क के लिए PHP 5 ज़रूरी है.

अगर आपके पास पहले से नहीं है, तो Zend फ़्रेमवर्क डाउनलोड करें और उसे अपने सर्वर पर अपलोड करें. फ़्रेमवर्क यहां उपलब्ध है: http://framework.zend.com/download/gdata.

आपको Zend लाइब्रेरी को शामिल करने के लिए, अपने PHP का include_path बदलना होगा. ऐसा करने के कई तरीके हैं, जो आपके सर्वर पर एडमिन के अधिकारों के लेवल पर निर्भर करते हैं. इस लाइन को लाइब्रेरी का इस्तेमाल करके, किसी भी PHP फ़ाइल में ज़रूरी स्टेटमेंट के ऊपर जोड़ना है:

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

इसकी जांच करने के लिए, डेमो/Zend/Gdata फ़ोल्डर की कमांड लाइन में इसे डालें और स्प्रेडशीट का डेमो चलाएं:

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

अगर वह काम करता है, तो आपको अपनी स्प्रेडशीट की एक सूची दिखेगी. अगर आपको गड़बड़ी का मैसेज मिलता है, तो जांच लें कि आपका शामिल किया गया पाथ सही तरीके से सेट किया गया है या नहीं. साथ ही, यह भी देखें कि आपने PHP 5 इंस्टॉल किया हुआ है या नहीं.

ग्लोबल फ़ंक्शन बनाना

हमारे ज़रिए समुदाय मैप के लिए लिखी जाने वाली सभी PHP स्क्रिप्ट में कॉमन कॉमन, वैरिएबल, और फ़ंक्शन का इस्तेमाल किया जाएगा, जिन्हें हम एक फ़ाइल में डाल देंगे.

फ़ाइल की शुरुआत में, हमारे पास Zend लाइब्रेरी को शामिल करने और लोड करने के लिए ज़रूरी विवरण होंगे. इसे स्प्रेडशीट-ClientLogin.php के उदाहरण से लिया गया है.

इसके बाद हम उन कॉन्सटेंट के बारे में बताएंगे जिनका इस्तेमाल सभी फ़ाइलों में किया जाएगा: स्प्रेडशीट कुंजी और दो वर्कशीट आईडी. अपनी स्प्रेडशीट की जानकारी पाने के लिए, उसे खोलें, "पब्लिश करें टैब" पर क्लिक करें और "पब्लिश करने के ज़्यादा विकल्प" पर क्लिक करें. फ़ाइल फ़ॉर्मैट की ड्रॉप-डाउन सूची से "ATOM" चुनें और "यूआरएल जनरेट करें" पर क्लिक करें. आपको कुछ ऐसा दिखेगा:

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

स्प्रेडशीट कुंजी, "/list/" के बाद आने वाली एक लंबी अक्षर और अंक वाली स्ट्रिंग होती है. इसके बाद, तीन वर्णों की वर्कशीट आईडी होती है. दूसरा वर्कशीट आईडी ढूंढने के लिए, "क्या शीट हैं" ड्रॉप-डाउन से दूसरी शीट चुनें.

इसके बाद, हम तीन फ़ंक्शन बनाएंगे: setupClient, getWkshtListFeed, और printFeed. सेट अप क्लाइंट में, हम अपना Gmail उपयोगकर्ता नाम और पासवर्ड सेट करेंगे, ClientLogin के साथ प्रमाणित करेंगे, और Zend_Gdata_spreadsheets ऑब्जेक्ट दिखाएंगे. getWkshtListFeed में, हम वैकल्पिक स्प्रेडशीट क्वेरी (लिंक) के साथ दी गई स्प्रेडशीट कुंजी और वर्कशीट आईडी के लिए स्प्रेडशीट सूची फ़ीड वापस करेंगे. printFeed फ़ंक्शन, Spreadsheets-ClientLogin.php उदाहरण से लिया गया है और डीबग करने में आपके लिए उपयोगी हो सकता है. वह एक फ़ीड ऑब्जेक्ट को लेगा और उसे स्क्रीन पर प्रिंट कर देगा.

ऐसा करने वाला PHP यहां दिखाया गया है (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++;
  }
}
 
?>

नए उपयोगकर्ता को रजिस्टर करना

नया उपयोगकर्ता रजिस्टर करने के लिए, हम चाहते हैं कि उपयोगकर्ता के लिए एचटीएमएल फ़ील्ड वाला टेक्स्ट फ़ील्ड और सबमिट बटन हो. साथ ही, स्प्रेडशीट बैकएंड में होनी चाहिए, ताकि उपयोगकर्ता को स्प्रेडशीट में जोड़ा जा सके.

PHP स्क्रिप्ट में, हम पहले ग्लोबल स्क्रिप्ट शामिल करते हैं और फिर GET वैरिएबल से उपयोगकर्ता नाम और पासवर्ड मान प्राप्त करते हैं. इसके बाद, हम स्प्रेडशीट क्लाइंट सेट अप करते हैं और क्वेरी स्ट्रिंग वाली उपयोगकर्ता वर्कशीट के लिए सूची फ़ीड का अनुरोध करते हैं, ताकि नतीजों में सिर्फ़ उन पंक्तियों तक पहुंचा जा सके जहां उपयोगकर्ता नाम के कॉलम में स्क्रिप्ट के लिए पास किया गया उपयोगकर्ता नाम मौजूद है. अगर हमें सूची के फ़ीड में कोई पंक्ति नहीं मिलती, तो हम यह जानकर सुरक्षित तरीके से कार्रवाई कर सकते हैं कि दिया गया उपयोगकर्ता नाम सबसे अलग है. सूची फ़ीड में कोई पंक्ति डालने से पहले, हम कॉलम की वैल्यू का एक असोसिएशन बनाते हैं: उपयोगकर्ता नाम, PHP के sha1 फ़ंक्शन का इस्तेमाल करके पासवर्ड को एन्क्रिप्ट (सुरक्षित) करने का तरीका, और सेशन के लिए फ़िलर वर्ण. इसके बाद, हम स्प्रेडशीट क्लाइंट पर InsertRow को जोड़ते हैं, ताकि हम असोसिएटिंग अरे, स्प्रेडशीट की, और वर्कशीट आईडी को पास कर सकें. अगर दिया गया ऑब्जेक्ट ListFeedEntry है, तो हम सबसे सफल! मैसेज देते हैं.

ऐसा करने वाला PHP यहां दिखाया गया है (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!";
}
?>

रजिस्ट्रेशन पेज पर, हम Maps API को शामिल कर सकते हैं, ताकि हम इसके XMLHttpRequest रैपर फ़ंक्शन का इस्तेमाल कर सकें, जिसे GDownloadUrl कहते हैं. जब उपयोगकर्ता 'सबमिट करें' बटन पर क्लिक करेगा, तो हमें टेक्स्ट फ़ील्ड से उपयोगकर्ता नाम और पासवर्ड मिल जाएगा. हम उसकी वैल्यू से पैरामीटर स्ट्रिंग बनाएंगे. इसके अलावा, स्क्रिप्ट के यूआरएल और पैरामीटर पर GDownloadUrl को कॉल भी करेंगे. हम संवेदनशील जानकारी भेज रहे हैं, इसलिए हम GDownloadUrl के एचटीटीपी POST वर्शन का इस्तेमाल कर रहे हैं (पैरामीटर को यूआरएल में जोड़ने के बजाय तीसरे आर्ग्युमेंट के रूप में भेजकर). कॉलबैक फ़ंक्शन में, हम सफल जवाब के लिए जांच करेंगे और उपयोगकर्ता को सही मैसेज देंगे.

रजिस्ट्रेशन पेज के नमूने के लिए स्क्रीनशॉट और कोड नीचे दिए गए हैं (communitymap_registrar.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>

उपयोगकर्ता के रूप में लॉग इन करना

उपयोगकर्ताओं को हमारे सिस्टम में साइन इन करने की अनुमति देने के लिए, हम उपयोगकर्ता को दिखने वाले एचटीएमएल पेज से उपयोगकर्ता नाम और पासवर्ड डालने के लिए कहेंगे. साथ ही, हम यह भी चाहते हैं कि लॉगिन जानकारी की पुष्टि करने के लिए, PHP स्क्रिप्ट, सेशन आईडी बनाएं, और लॉगिन पेज पर वापस ले जाकर कुकी सेट करें. उपयोगकर्ता, बाद के पेजों पर सेशन कुकी के ज़रिए लॉग इन रहेगा.

PHP स्क्रिप्ट में, हम पहले ग्लोबल स्क्रिप्ट शामिल करते हैं और फिर GET वैरिएबल से उपयोगकर्ता नाम और पासवर्ड मान प्राप्त करते हैं. इसके बाद, हम स्प्रेडशीट क्लाइंट सेट अप करते हैं और क्वेरी स्ट्रिंग वाली उपयोगकर्ता वर्कशीट के लिए सूची फ़ीड का अनुरोध करते हैं, ताकि नतीजों में सिर्फ़ उन पंक्तियों तक पहुंचा जा सके जहां उपयोगकर्ता नाम के कॉलम में स्क्रिप्ट के लिए पास किया गया उपयोगकर्ता नाम मौजूद है.

दिखाई गई पंक्ति में, हम जांच करेंगे कि पास किए गए पासवर्ड का हैश स्प्रेडशीट में स्टोर किए गए हैश से मेल खाता है. अगर यह सही है, तो हम md5, uniqid, और रैंड फ़ंक्शन का इस्तेमाल करके सेशन आईडी बनाएंगे. इसके बाद हम स्प्रेडशीट की सेशन वाली पंक्ति अपडेट कर देंगे. साथ ही, पंक्ति अपडेट हो जाने पर उसे स्क्रीन पर आउटपुट कर देंगे.

इसके लिए, आपको नीचे दिए गए कोड (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"];
    }
  }
}
?>

लॉगिन पेज पर, हम Maps API को फिर से शामिल कर सकते हैं, ताकि हम उसके XMLHttpRequest रैपर फ़ंक्शन का इस्तेमाल कर सकें, जिसे GDownloadUrl कहते हैं. जब उपयोगकर्ता 'सबमिट करें' बटन पर क्लिक करेगा, तो हमें टेक्स्ट फ़ील्ड से उपयोगकर्ता नाम और पासवर्ड मिल जाएगा. साथ ही, क्वेरी पैरामीटर के साथ स्क्रिप्ट का यूआरएल बनाया जा सकेगा और स्क्रिप्ट के यूआरएल पर GDownloadUrl को कॉल किया जा सकेगा. कॉलबैक फ़ंक्शन में, हम स्क्रिप्ट आईडी से मिलने वाली सेशन आईडी वाली कुकी सेट करेंगे. अगर कोई गड़बड़ी नहीं दिखती है, तो एक गड़बड़ी का मैसेज देंगे. setCookie फ़ंक्शन, w3c JavaScript ट्यूटोरियल के हिसाब से कुकी.js से आता है: http://www.w3schools.com/js/js_cookies.asp.

लॉगिन पेज का नमूना देखने के लिए, नीचे स्क्रीनशॉट और कोड दिखाए गए हैं (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>

उपयोगकर्ताओं को मैप पर जगहें जोड़ने की अनुमति देना

उपयोगकर्ता को हमारे मैप पर स्थान जोड़ने की अनुमति देने के लिए, हम उपयोगकर्ता को दिखाई देने वाले एचटीएमएल पेज को उस स्थान की जानकारी देने के साथ-साथ, दो PHP स्क्रिप्ट चाहते हैं - एक यह देखने के लिए कि वे हमारी सेट की हुई कुकी से लॉग इन हैं और दूसरी, जगह की जानकारी वाली वर्कशीट में जगह की जानकारी जोड़ने के लिए.

उपयोगकर्ता की लॉग इन होने वाली पहली स्क्रिप्ट में, हम पहले ग्लोबल स्क्रिप्ट को शामिल करते हैं. इसके बाद, जीईटी वैरिएबल से सेशन की वैल्यू पाते हैं. इसके बाद, हम स्प्रेडशीट क्लाइंट सेट अप करते हैं और क्वेरी स्ट्रिंग वाली उपयोगकर्ता वर्कशीट के लिए सूची फ़ीड का अनुरोध करते हैं, ताकि नतीजों को सिर्फ़ उन पंक्तियों में दिखाया जा सके जहां सेशन कॉलम, स्क्रिप्ट में पास की गई सेशन वैल्यू के बराबर है. इसके बाद, हम उस फ़ीड (जो हमारे कॉलम के हेडर से जुड़ी है) की कस्टम एंट्री को दोहराते हैं. साथ ही, अगर कोई सेशन मौजूद है, तो उस सेशन से जुड़ा उपयोगकर्ता नाम भी प्रिंट कर दिया जाता है.

इसके लिए, आपको नीचे दिए गए फ़ॉर्म (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();
    }
  }
}
?>

दूसरी PHP स्क्रिप्ट में, जो उपयोगकर्ता को जगह जोड़ने की सुविधा देता है, हम सबसे पहले समुदायमैप_checksession.php से कोड कॉपी करते हैं. इससे यह पक्का होता है कि उपयोगकर्ता अब भी लॉग इन और मान्य है. जब हमें उपयोगकर्ता शीट से कोई मान्य उपयोगकर्ता नाम वापस मिल जाता है, तो हमें GET वैरिएबल से जगह, अक्षांश, और lng वैल्यू मिलती हैं. हम उन सभी वैल्यू को एक असोसिएट श्रेणी में रखते हैं और हम PHP के date() फ़ंक्शन का इस्तेमाल करके एक "date" वैल्यू भी जोड़ते हैं, ताकि हमें पता चल सके कि उपयोगकर्ता ने जगह को कब जोड़ा है. हम उस असोसिएशन को अरे, स्प्रेडशीट की कॉन्सटेंट और जगहों की वर्कशीट के आईडी को लगातार InsertRow फ़ंक्शन में पास करते हैं. अगर स्प्रेडशीट में नई जगह की पंक्ति जोड़ी गई, तो हम "हो गया" आउटपुट देते हैं. अगर आपको इस चरण में कोई गड़बड़ी मिल रही है, तो ऐसा कॉलम हेडर के नामों में अंतर की वजह से हो सकता है. असोसिएट श्रेणी की कुंजियां, स्प्रेडशीट कुंजी और वर्कशीट आईडी की ओर से दी गई वर्कशीट में मौजूद कॉलम हेडर से मेल खानी चाहिए.

इसके लिए, आपको नीचे दिए गए कोड (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";
  }
}

?>

स्थान जोड़ें पेज पर, हम Maps API को फिर से शामिल कर सकते हैं, ताकि हम GDownloadUrl का इस्तेमाल करके मैप बना सकें. पेज लोड होने के बाद, हम सेशन वैल्यू को फिर से पाने के लिए, BigQuery के getCookie फ़ंक्शन का इस्तेमाल करते हैं. सेशन स्ट्रिंग शून्य या खाली होने पर, हम गड़बड़ी का एक मैसेज दिखाते हैं. अगर ऐसा नहीं है, तो हम सत्र में भेजते हुए maps.checksession.php पर GDownloadUrl को कॉल करते हैं. अगर वह सफलतापूर्वक उपयोगकर्ता नाम वापस करता है, तो हम उपयोगकर्ता को स्वागत मैसेज दिखाते हैं, ऐड-ए-लोकेशन फ़ॉर्म दिखाते हैं, और मैप लोड करते हैं. इस फ़ॉर्म में पता फ़ील्ड, मैप, और जगह के नाम, अक्षांश, और देशांतर के लिए टेक्स्ट फ़ील्ड होते हैं. अगर उपयोगकर्ता को पहले से जगह के अक्षांश/देशांतर की जानकारी नहीं है, तो वे फ़ॉर्म में अपना पता डालकर और "सबमिट करें" दबाकर, इसे वेब पेज पर जोड़ सकते हैं. यह Map API के GClientGeocoder पर कॉल करेगा, जो पता मिलने पर मैप पर मार्कर लगा देगा. साथ ही, अक्षांश/देशांतर की फ़ील्ड को अपने-आप भर देगा.

उपयोगकर्ता संतुष्ट होने पर, वह "जगह की जानकारी जोड़ें" बटन दबा सकता है. फिर JavaScript में, हम उपयोगकर्ता, स्थान, अक्षांश और lng के लिए मान प्राप्त करेंगे, और उन्हें GDownloadUrl के साथ networkmap_addlocation.php स्क्रिप्ट पर भेज देंगे.

अगर वह स्क्रिप्ट सफल होती है, तो हम स्क्रीन पर एक सफल मैसेज दिखाएंगे.

नमूने के तौर पर जोड़ी गई जगह वाले पेज का स्क्रीनशॉट और कोड नीचे दिखाया गया है (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>

मैप बनाना

आपने पहले चरण में जगहों की वर्कशीट को सार्वजनिक किया है, इसलिए उनका मैप बनाने के लिए किसी सर्वर साइड प्रोग्रामिंग की ज़रूरत नहीं है. दरअसल, किसी भी प्रोग्रामिंग की ज़रूरत नहीं है. आप इस स्प्रेडशीट -> मैप विज़र्ड का इस्तेमाल कर सकते हैं और मैप के लिए ज़रूरी सभी कोड जनरेट करेंगे. विज़ार्ड, पेज में ऐसी स्क्रिप्ट टैग को जोड़कर पेज पर वर्कशीट एंट्री को डाउनलोड करता है जो फ़ीड के JSON आउटपुट को जोड़ती हैं. साथ ही, एक कॉलबैक फ़ंक्शन तय करता है, जिसे JSON डाउनलोड होने के बाद कॉल किया जाता है. ज़्यादा जानकारी यहां उपलब्ध है.

ऐसा करने के लिए सैंपल एचटीएमएल कोड यहां दिया गया है: mainmap.htm. स्क्रीनशॉट नीचे दिखाया गया है:

नतीजा

उम्मीद है कि अब आपके सर्वर पर, उपयोगकर्ता से मिला मैप सिस्टम काम कर रहा है. इस लेख में, इस सिस्टम के ज़रूरी पहलुओं के लिए ज़रूरी बुनियादी कोड दिया गया है. हालांकि, अब आप Zend स्प्रेडशीट लाइब्रेरी के बारे में जानते हैं, तो आपको अपनी खास ज़रूरतों को पूरा करने के लिए सिस्टम को बढ़ाने का मौका मिल जाना चाहिए. अगर आपको इस दौरान समस्याएं आती हैं, तो याद रखें कि आप डीबग करने के लिए JavaScript में echo कमांड या JavaScript में GLog.write() मैप एपीआई का इस्तेमाल कर सकते हैं. साथ ही, ज़्यादा मदद के लिए, आप हमेशा Maps API या स्प्रेडशीट एपीआई डेवलपर फ़ोरम में पोस्ट कर सकते हैं.