נובמבר 2007
יעד
האינטרנט מלא בקהילות שממוקמות בין מיקומים גיאוגרפיים ותחומי עניין: אנשים שאוהבים מוזיאונים, קתדרלות אירופאיות, פארקים לאומיים וכו'. לכן, המפתח שלהן (כמוך) חייב תמיד ליצור מערכת שבה משתמשים יוכלו להוסיף למפה מקומות עם תיוג גיאוגרפי, וזה בדיוק מה שנעשה כאן. בסוף המאמר הזה תוצג לכם מערכת שבה משתמשים יכולים להירשם למקומות, להוסיף מיקומים גיאוגרפיים ולהוסיף מקומות. המערכת תשתמש ב-AJAX עבור ממשק הקצה, ב-PHP עבור סקריפטים בצד השרת וב-Google Sheets לאחסון. אם אתם רגילים להשתמש במסדי נתונים של MySQL לאחסון, אפשר במקום זאת לשנות את הקוד בקלות כדי להשתמש בקצה עורפי של מסדי נתונים של MySQL.
המאמר מחולק לשלבים הבאים:
- הגדרת הגיליון האלקטרוני
- עבודה עם מסגרת Zend Gdata
- יצירת פונקציות גלובליות
- רישום משתמש חדש
- התחברות למשתמש
- איך לאפשר למשתמשים להוסיף מקומות במפה
- יצירת המפה
- סיכום
הגדרת הגיליון האלקטרוני
נשתמש בגיליונות אלקטרוניים של Google כדי לאחסן את כל הנתונים עבור המערכת הזו. יש שני סוגים של נתונים שעלינו לאחסן: פרטי חשבון משתמש ומקומות שנוספו על ידי המשתמש, כך שניצור גיליון עבודה אחד לכל סוג נתונים. נקיים אינטראקציה עם גיליונות העבודה באמצעות פיד הרשימה שלהם, המסתמך על השורה הראשונה בגיליון העבודה שמכיל את תוויות העמודות, ואת כל השורות הבאות שמכילות נתונים.
נכנסים לכתובת docs.google.com ויוצרים גיליון אלקטרוני חדש. משנים את ברירת המחדל של גיליון העבודה ל-"Users" ויוצרים עמודות בשם "user", "password" ו-"session". לאחר מכן מוסיפים עוד גיליון, משנים את השם שלו ל'מיקומים' ויוצרים עמודות בשם 'user', 'סטטוס', 'lat', 'ng' ו-'date'. אם לדעתך אין צורך לעבוד באופן ידני, הורד את התבנית הזו וייבא אותה לגיליונות אלקטרוניים של Google באמצעות הפקודה 'קובץ' > 'ייבוא'.
יש לשמור על הפרטיות של פרטי חשבון המשתמש (גלויים רק לבעלים של הגיליון האלקטרוני), והמקומות שנוספו על ידי משתמשים יוצגו במפה ציבורית. למזלנו, גיליונות אלקטרוניים של Google מאפשרים לכם לבחור באופן סלקטיבי אילו גיליונות עבודה בגיליון אלקטרוני יכולים להיות ציבוריים, ואילו צריכים להישאר פרטיים (ברירת מחדל). כדי לפרסם את גיליון העבודה "מיקומים", לוחצים על הכרטיסייה "פרסום", לוחצים על "פרסום עכשיו", מסמנים את תיבת הסימון "פרסום מחדש באופן אוטומטי" ולאחר מכן, בתפריט הנפתח "אילו חלקים?" בוחרים באפשרות "גיליון 'מיקומים' בלבד". האפשרויות הנכונות מוצגות בצילום המסך שבהמשך:

עבודה עם מסגרת Zend GData
ה-API של Google Sheets מספק ממשק HTTP לפעולות CRUD, כמו אחזור שורות, הוספת שורות, עדכון שורות ומחיקת שורות. ה-Zend Framework מספק wrapper של PHP בנוסף ל-API (ולממשקי ה-API האחרים של GData), כך שאין צורך לדאוג ליישום של פעולות HTTP גולמיות. מסגרת Zend מחייבת PHP 5.
אם עדיין לא עשיתם זאת, מורידים את ה-Zend framework ומעלים אותו לשרת. המסגרת זמינה כאן: http://framework.zend.com/download/gdata.
צריך לשנות את ה-PHP include_path כך שיכלול את ספריית Zend. יש כמה דרכים לעשות זאת, בהתאם לרמת הרשאות הניהול בשרת שלכם. דרך אחת היא להוסיף את השורה הזו מעל להצהרות החובה בכל קובצי 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 ולוחצים על 'יצירת כתובת URL'. תראו משהו כזה:
http://spreadsheets.google.com/feeds/list/o16162288751915453340.4016005092390554215/od6/public/basic
מפתח הגיליון האלקטרוני הוא המחרוזת האלפאנומרית הארוכה אחרי "/list/ ", ומזהה גיליון העבודה הוא המחרוזת הארוכה בת 3 התווים. כדי למצוא את המזהה של גיליון העבודה השני, בוחרים את הגיליון האחר מהתפריט הנפתח 'אילו גיליונות?'.
לאחר מכן ניצור 3 פונקציות: setupClient (הגדרה של הלקוח, getWkshtListFeed ו-printFeed). ב-SetupClient, נגדיר את שם המשתמש והסיסמה של 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++; } } ?>
רישום משתמש חדש
כדי לרשום משתמש חדש, אנחנו רוצים שדף HTML הפונה אל המשתמש יכלול שדות טקסט ולחצן שליחה, וסקריפט PHP בקצה העורפי יוסיף את המשתמש לגיליון האלקטרוני.
בסקריפט של PHP, קודם אנחנו כוללים את הסקריפט הגלובלי, ולאחר מכן מקבלים את הערכים של שם המשתמש והסיסמה מהמשתנה GET. לאחר מכן נגדיר לקוח 'גיליונות אלקטרוניים', ומבקשים את פיד הרשימה עבור גיליון העבודה של המשתמשים עם מחרוזת שאילתה כדי להגביל את התוצאות רק לשורות שבהן עמודת שם המשתמש זהה לשם המשתמש שהועבר לסקריפט. אם לא יופיעו שורות בתוצאת העדכון של הרשימה, נוכל להמשיך בידיעה ששם המשתמש שהועבר הוא ייחודי. לפני הוספת שורה בפיד הרשימה, אנחנו יוצרים מערך אסוציאטיבי של ערכי העמודות: שם המשתמש, הצפנה של הסיסמה באמצעות פונקציית ה-sha1 של PHP ודמות מילוי אחרת בסשן. לאחר מכן, אנחנו קוראים ל-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!"; } ?>
בדף הרישום נוכל לכלול את ה-API של מפות Google כדי שנוכל להשתמש בפונקציית wrapper של XMLHttpRequest שנקראת GDownloadUrl. כאשר המשתמש לוחץ על לחצן השליחה, אנחנו מקבלים את שם המשתמש והסיסמה משדות הטקסט, יוצרים מחרוזת פרמטרים מהערכים שלו וקוראים ל-GDownloadUrl בכתובת האתר ובפרמטרים של הסקריפט. מאחר שאנחנו שולחים מידע רגיש, אנחנו משתמשים בגרסת HTTP POST של GDownloadUrl (על ידי שליחת הפרמטרים כארגומנט השלישי, במקום לצרף אותם לכתובת ה-URL). בפונקציית הקריאה החוזרת, נבדוק אם יש תגובה מוצלחת ויצירת מסר מתאים למשתמש.
צילום מסך וקוד מוצגים למטה עבור דף רישום לדוגמה (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>
התחברות למשתמש
כדי לאפשר למשתמשים להיכנס למערכת שלנו, נרצה שדף HTML הפונה אל המשתמש יבקש מהם את שם המשתמש והסיסמה שלהם - וסקריפט PHP כדי לאמת את פרטי ההתחברות, ליצור מזהה הפעלה ולהעביר אותו חזרה לדף ההתחברות כדי להגדיר קובץ cookie. המשתמש יישאר מחובר באמצעות קובץ ה-cookie של ההפעלה בדפים הבאים.
בסקריפט של PHP, קודם אנחנו כוללים את הסקריפט הגלובלי, ולאחר מכן מקבלים את הערכים של שם המשתמש והסיסמה מהמשתנה GET. לאחר מכן נגדיר לקוח 'גיליונות אלקטרוניים', ומבקשים את פיד הרשימה עבור גיליון העבודה של המשתמשים עם מחרוזת שאילתה כדי להגביל את התוצאות רק לשורות שבהן עמודת שם המשתמש זהה לשם המשתמש שהועבר לסקריפט.
בשורה שמוחזרת, נבדוק שה-hash של הסיסמה שהועברה תואם להצפנת הגיבוב ששמורה בגיליון האלקטרוני. אם כן, ניצור מזהה סשן באמצעות הפונקציות md5 , uniqid ו-rand. לאחר מכן נעדכן את השורה בגיליון האלקטרוני עם הפעילות באתר, ופלט אותה למסך אם עדכון השורה יושלם בהצלחה.
ה-PHP שמוצג עכשיו (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"]; } } } ?>
בדף ההתחברות, נוכל לכלול שוב את ה-API של מפות Google כדי שנוכל להשתמש בפונקציית wrapper של XMLHttpRequest שנקראת GDownloadUrl. כאשר המשתמש לוחץ על לחצן השליחה, אנחנו מקבלים את שם המשתמש והסיסמה משדות הטקסט, בונים את כתובת האתר של הסקריפט עם הפרמטרים של השאילתה וקוראים ל-GDownloadUrl בכתובת האתר של הסקריפט. במסגרת פונקציית הקריאה החוזרת, נגדיר קובץ cookie עם מזהה ההפעלה שמוחזר על ידי הסקריפט, או פלט הודעת שגיאה אם לא הוחזר ערך. הפונקציה setcookie מגיעה מקובץ cookie.js שמבוסס על מדריך JavaScript של w3c: 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>
לאפשר למשתמשים להוסיף מקומות במפה
כדי לאפשר למשתמש להוסיף מקומות למפה שלנו, נזדקק לדף HTML הפונה למשתמש כדי לאפשר לו לספק מידע על המיקום, ושני סקריפטים של PHP - אחד כדי לבדוק אם הוא מחובר באמצעות קובץ ה-cookie שהוגדר, ואחד אחר כדי להוסיף את המיקום לגיליון העבודה של המיקומים.
בסקריפט ה-PHP הראשון שבודק אם משתמש מחובר, קודם כל אנחנו כוללים את הסקריפט הגלובלי ולאחר מכן מקבלים את ערך הסשן מהמשתנה GET. לאחר מכן נגדיר לקוח 'גיליונות אלקטרוניים', ומבקשים את פיד הרשימה עבור גיליון העבודה של המשתמשים עם מחרוזת שאילתה כדי להגביל את התוצאות רק לשורות שבהן עמודת הסשן שווה לערך הסשן שמועבר לסקריפט. לאחר מכן אנחנו חוזרים על הערכים המותאמים אישית של הפיד (אלה שתואמים לכותרות העמודות שלנו), ומדפיסים את שם המשתמש התואם של הסשן, אם קיים.
ה-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 השני שמאפשר למשתמש להוסיף מיקום, אנחנו מעתיקים את הקוד מ-communitymap_checksession.php כדי לוודא שהמשתמש עדיין מחובר ותקף. כשאנחנו מקבלים שם משתמש חוקי מגיליון המשתמשים, אנחנו מקבלים את ערכי המקום, הרוחב וה-Lng של משתנה GET. אנחנו מכניסים את כל הערכים האלה למערך אסוציאטיבי, ומוסיפים גם ערך "תאריך" באמצעות פונקציית התאריך() של PHP, כדי שנוכל לדעת מתי המשתמש הוסיף את המקום. אנחנו מעבירים את המערך האסוציאטיבי הזה, את המפתח הקבוע של הגיליונות האלקטרוניים ואת המזהה של גיליון העבודה של המיקומים, לפונקציית InsertRow. לאחר מכן אנחנו יוצרים פלט של 'הצלחה' אם השורה של המיקום החדש נוספה לגיליון האלקטרוני. אם מופיעה שגיאה בשלב הזה, סביר להניח שהסיבה לכך היא חוסר התאמה בשמות של העמודות. המפתחות במערך האסוציאטיבי חייבים להתאים לכותרות העמודות בגיליון העבודה שצוינו על ידי מפתח הגיליון האלקטרוני ומזהה גיליון העבודה.
ה-PHP שמוצג עכשיו (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"; } } ?>
בדף הוספת המיקום, נוכל לכלול שוב את ה-API של מפות Google כדי שנוכל להשתמש ב-GDownloadUrl וליצור מפה. לאחר שהדף נטען, אנחנו משתמשים בפונקציה getcookie מ-cookies.js כדי לאחזר את ערך הפעילות באתר. אם מחרוזת הסשן היא ריקה או ריקה, יוצג פלט של הודעת שגיאה. אם לא, אנו קוראים ל-GDownloadUrl ב-map.checksession.php, השולחים בפעילות באתר. אם הפעולה הזו מחזירה בהצלחה שם משתמש, אנחנו מציגים הודעת פתיחה למשתמש, חושפים את טופס הוספת המיקום וטוענים את המפה. הטופס כולל שדות טקסט, מפה ושדות טקסט של שם המקום, קו הרוחב וקו האורך. אם המשתמש אינו יודע עדיין את קו הרוחב/קו האורך של המיקום, הוא יכול לבצע קידוד גיאוגרפי באמצעות הזנת הכתובת שלו בטופס ולחיצה על 'שלח'. פעולה זו תשלח קריאה ל-GClientGecoder של ממשק ה-API של המפה, שימקם סמן במפה אם הוא ימצא את הכתובת, ויאכלס באופן אוטומטי את שדות הטקסט שבקו הרוחב/קו האורך.
כשהמשתמש מרוצה, הוא יכול ללחוץ על הלחצן 'הוסף מיקום'. לאחר מכן, ב-JavaScript, נקבל את הערכים של המשתמש, המקום, הרוחב וה-lng, ונשלח אותם לסקריפט Communitymap_addlocation.php עם GDownloadUrl
.
אם הסקריפט הזה יחזיר הצלחה, נעביר הודעת הצלחה למסך.
צילום מסך וקוד מוצגים למטה עבור דוגמה לדף מיקום (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 של הפיד, ומציין פונקציית קריאה חוזרת (callback) שנקראת ברגע שה-JSON יורד. מידע נוסף זמין כאן.
קוד HTML לדוגמה לשם כך זמין כאן: mainmap.htm. צילום מסך מוצג כאן:

סיכום
אנחנו מקווים שעכשיו יש לכם מערכת מפות משלכם שתרמה למשתמשים. המאמר הזה מספק את הקוד הבסיסי ביותר שנחוץ להיבטים החיוניים של המערכת הזו, אבל עכשיו, אחרי שהכרתם את הספרייה של Zend spreadsheets, תוכלו להרחיב את המערכת כך שתענה על הצרכים הספציפיים שלכם. אם תיתקלו בשגיאות בדרך, זכרו שתוכלו להשתמש בפקודה echo
ב-PHP או ב-GLog.write()
של ה-API של מפות Google ב-JavaScript לצורך ניפוי באגים, ותמיד אפשר לפרסם בפורומים למפתחים של Maps API או Sheets API כדי לקבל עזרה נוספת.