พฤศจิกายน 2007
วัตถุประสงค์
บนเว็บมีชุมชนมากมายที่เน้นภูมิศาสตร์และความสนใจ เช่น ผู้ที่ชื่นชอบพิพิธภัณฑ์ มหาวิหารในยุโรป อุทยานแห่งชาติ ฯลฯ ดังนั้นจึงจำเป็นอย่างยิ่งที่นักพัฒนาซอฟต์แวร์ (เช่นคุณ) จะต้องสร้างระบบที่ผู้ใช้สามารถมีส่วนร่วมในการเพิ่มสถานที่ที่มีการติดแท็กตำแหน่งลงในแผนที่ และนั่นคือสิ่งที่เราจะทำกันที่นี่ เมื่ออ่านบทความนี้จบ คุณจะมีระบบที่ผู้ใช้สามารถลงทะเบียน เข้าสู่ระบบ และเพิ่มสถานที่ที่มีการติดแท็กตำแหน่งได้ ระบบจะใช้ AJAX สำหรับส่วนหน้า, PHP สำหรับการเขียนสคริปต์ฝั่งเซิร์ฟเวอร์ และ Google สเปรดชีตสำหรับพื้นที่เก็บข้อมูล หากคุ้นเคยกับการใช้ฐานข้อมูล MySQL สำหรับการจัดเก็บ คุณสามารถแก้ไขโค้ดที่นี่เพื่อใช้แบ็กเอนด์ฐานข้อมูล MySQL แทนได้อย่างง่ายดาย
บทความนี้แบ่งออกเป็นขั้นตอนต่อไปนี้
- การตั้งค่าสเปรดชีต
- การทำงานกับ Zend Gdata Framework
- การสร้างฟังก์ชันส่วนกลาง
- การลงทะเบียนผู้ใช้ใหม่
- การบันทึกการเข้าสู่ระบบของผู้ใช้
- การอนุญาตให้ผู้ใช้เพิ่มสถานที่ในแผนที่
- การสร้างแผนที่
- สรุป
การตั้งค่าสเปรดชีต
เราจะใช้ Google สเปรดชีตเพื่อจัดเก็บข้อมูลทั้งหมดของระบบนี้ เราต้องจัดเก็บข้อมูล 2 ประเภท ได้แก่ ข้อมูลบัญชีผู้ใช้และสถานที่ที่ผู้ใช้เพิ่ม ดังนั้นเราจะสร้างเวิร์กชีต 1 รายการสำหรับข้อมูลแต่ละประเภท เราจะโต้ตอบกับเวิร์กชีตโดยใช้ฟีดรายการ ซึ่งอิงตามแถวแรกในเวิร์กชีตที่มีป้ายกำกับคอลัมน์ และแต่ละแถวถัดไปที่มีข้อมูล
ไปที่ docs.google.com แล้วสร้างสเปรดชีตใหม่ เปลี่ยนชื่อสเปรดชีตเริ่มต้นเป็น "Users" และสร้างคอลัมน์ชื่อ "user", "password" และ "session" จากนั้นเพิ่มชีตอื่น เปลี่ยนชื่อเป็น "Locations" และสร้างคอลัมน์ชื่อ "user", "status", "lat", "lng" และ "date" หรือหากไม่ต้องการทำงานด้วยตนเองทั้งหมด ให้ดาวน์โหลดเทมเพลตนี้แล้วนำเข้าไปยัง Google สเปรดชีตผ่านคำสั่งไฟล์->นำเข้า
คุณต้องเก็บข้อมูลบัญชีผู้ใช้ไว้เป็นส่วนตัว (มองเห็นได้เฉพาะเจ้าของสเปรดชีต ซึ่งก็คือคุณ) ในขณะที่สถานที่ที่ผู้ใช้เพิ่มจะแสดงบนแผนที่ที่มองเห็นได้แบบสาธารณะ โชคดีที่ Google สเปรดชีตช่วยให้คุณเลือกได้ว่าจะให้เวิร์กชีตใดในสเปรดชีตเป็นแบบสาธารณะและเวิร์กชีตใดควรเป็นแบบส่วนตัว (ค่าเริ่มต้น) หากต้องการเผยแพร่เวิร์กชีต "สถานที่ตั้ง" ให้คลิกแท็บ "เผยแพร่" คลิก "เผยแพร่เลย" เลือกช่องทําเครื่องหมาย "เผยแพร่ซ้ำโดยอัตโนมัติ" จากนั้นในเมนูแบบเลื่อนลง "ส่วนใด" ให้เลือก "ชีต 'สถานที่ตั้ง' เท่านั้น" ตัวเลือกที่ถูกต้องจะแสดงในภาพหน้าจอด้านล่าง
การทำงานกับ Zend GData Framework
Google Spreadsheets API มีอินเทอร์เฟซ HTTP สำหรับการดำเนินการ CRUD เช่น การดึงข้อมูลแถว การแทรกแถว การอัปเดตแถว และการลบแถว Zend Framework มี Wrapper PHP อยู่เหนือ API (และ GData API อื่นๆ) เพื่อให้คุณไม่ต้องกังวลเกี่ยวกับการใช้การดำเนินการ HTTP ดิบ Zend Framework ต้องใช้ PHP 5
หากยังไม่มี ให้ดาวน์โหลด Zend Framework แล้วอัปโหลดไปยังเซิร์ฟเวอร์ ดูเฟรมเวิร์กได้ที่ http://framework.zend.com/download/gdata
คุณควรแก้ไข include_path ของ PHP เพื่อรวมไลบรารี Zend คุณทำได้หลายวิธี ขึ้นอยู่กับระดับสิทธิ์การดูแลระบบที่คุณมีในเซิร์ฟเวอร์ วิธีหนึ่งคือการเพิ่มบรรทัดนี้เหนือคำสั่ง require ในไฟล์ PHP ใดก็ตามที่ใช้ไลบรารี
ini_set("include_path", ".:/usr/lib/php:/usr/local/lib/php:../../../library/");
หากต้องการทดสอบ ให้เรียกใช้การสาธิตสเปรดชีตโดยป้อนคำสั่งต่อไปนี้ในบรรทัดคำสั่งในโฟลเดอร์ demos/Zend/Gdata
php Spreadsheet-ClientLogin.php --user=YourGMailUsername --pass=YourPassword
หากใช้งานได้ คุณจะเห็นรายการสเปรดชีตของคุณแสดงอยู่ หากพบข้อผิดพลาด ให้ตรวจสอบว่าได้ตั้งค่าเส้นทางการรวมอย่างถูกต้องและติดตั้ง PHP 5 แล้ว
การสร้างฟังก์ชันส่วนกลาง
สคริปต์ PHP ทั้งหมดที่เราจะเขียนสำหรับแผนที่ชุมชนจะใช้การรวม ตัวแปร และฟังก์ชันทั่วไป ซึ่งเราจะใส่ไว้ในไฟล์เดียว
ที่จุดเริ่มต้นของไฟล์ เราจะมีคำสั่งที่จำเป็นในการรวมและโหลดไลบรารี Zend ซึ่งนำมาจากตัวอย่าง Spreadsheets-ClientLogin.php
จากนั้นเราจะกำหนดค่าคงที่ที่จะใช้ในไฟล์ต่างๆ ได้แก่ คีย์ของสเปรดชีตและรหัสของเวิร์กชีต 2 รายการ หากต้องการดูข้อมูลสำหรับสเปรดชีต ให้เปิดสเปรดชีต คลิก "แท็บเผยแพร่" แล้วคลิก "ตัวเลือกการเผยแพร่เพิ่มเติม" เลือก "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!";
}
?>
ในหน้าลงทะเบียน เราสามารถรวม Maps API เพื่อให้ใช้ฟังก์ชัน Wrapper ของ XMLHttpRequest ที่ชื่อ GDownloadUrl ได้ เมื่อผู้ใช้คลิกปุ่มส่ง เราจะได้รับชื่อผู้ใช้และรหัสผ่านจากช่องข้อความ สร้างสตริงพารามิเตอร์จากค่า และเรียก GDownloadUrl ใน URL ของสคริปต์และพารามิเตอร์ เนื่องจากเราจะส่งข้อมูลที่ละเอียดอ่อน จึงใช้ GDownloadUrl เวอร์ชัน HTTP POST (โดยส่งพารามิเตอร์เป็นอาร์กิวเมนต์ที่ 3 แทนการต่อท้าย 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 เพื่อยืนยันข้อมูลการเข้าสู่ระบบ สร้างรหัสเซสชัน และส่งกลับไปยังหน้าเข้าสู่ระบบเพื่อตั้งค่าคุกกี้ ผู้ใช้จะยังคงเข้าสู่ระบบผ่านคุกกี้ของเซสชันในหน้าต่อๆ ไป
ในสคริปต์ PHP เราจะรวมสคริปต์ส่วนกลางก่อน จากนั้นจึงรับค่าชื่อผู้ใช้และรหัสผ่านจากตัวแปร GET จากนั้นเราจะตั้งค่าไคลเอ็นต์สเปรดชีต และขอฟีดรายการสำหรับเวิร์กชีตผู้ใช้ด้วยสตริงการค้นหาเพื่อจำกัดผลลัพธ์ให้แสดงเฉพาะแถวที่คอลัมน์ชื่อผู้ใช้เท่ากับชื่อผู้ใช้ที่ส่งไปยังสคริปต์
ในแถวที่แสดงผล เราจะตรวจสอบว่าแฮชของรหัสผ่านที่ส่งมาตรงกับแฮชที่จัดเก็บไว้ในสเปรดชีต หากเป็นเช่นนั้น เราจะสร้างรหัสเซสชันโดยใช้ฟังก์ชัน 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"];
}
}
}
?>
ในหน้าเข้าสู่ระบบ เราสามารถรวม Maps API อีกครั้งเพื่อให้ใช้ฟังก์ชัน Wrapper ของ XMLHttpRequest ที่ชื่อ GDownloadUrl ได้ เมื่อผู้ใช้คลิกปุ่มส่ง เราจะรับชื่อผู้ใช้และรหัสผ่านจากช่องข้อความ สร้าง URL ของสคริปต์ด้วยพารามิเตอร์การค้นหา และเรียกใช้ GDownloadUrl ใน URL ของสคริปต์ ในฟังก์ชันเรียกกลับ เราจะตั้งค่าคุกกี้ที่มีรหัสเซสชันที่สคริปต์ส่งคืน หรือแสดงข้อความแสดงข้อผิดพลาดหากไม่มีการส่งคืน ฟังก์ชัน setCookie มาจาก cookies.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 2 รายการ ได้แก่ สคริปต์หนึ่งสำหรับตรวจสอบว่าผู้ใช้ได้เข้าสู่ระบบผ่านคุกกี้ที่เราตั้งค่าไว้ และอีกสคริปต์หนึ่งสำหรับเพิ่มสถานที่ลงในเวิร์กชีตสถานที่
ในสคริปต์ 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 ที่ 2 ซึ่งอนุญาตให้ผู้ใช้เพิ่มสถานที่ตั้ง เราจะจำลองโค้ดจาก communitymap_checksession.php ก่อนเพื่อให้แน่ใจว่าผู้ใช้ยังคงเข้าสู่ระบบและใช้งานได้ จากนั้นเมื่อได้รับชื่อผู้ใช้ที่ถูกต้องจากชีตผู้ใช้ เราจะรับค่าสถานที่ ละติจูด และลองจิจูดจากตัวแปร GET เราจะใส่ค่าทั้งหมดเหล่านั้นลงในอาร์เรย์แบบเชื่อมโยง และเพิ่มค่า "date" โดยใช้ฟังก์ชัน date() ของ 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";
}
}
?>
ในหน้าเพิ่มสถานที่ เราสามารถรวม Maps API อีกครั้งเพื่อให้ใช้ GDownloadUrl และสร้างแผนที่ได้ หลังจากโหลดหน้าเว็บแล้ว เราจะใช้ฟังก์ชัน getCookie จาก cookies.js เพื่อดึงค่าเซสชัน หากสตริงเซสชันเป็นค่าว่างหรือว่างเปล่า เราจะแสดงข้อความแสดงข้อผิดพลาด หากไม่ถูกต้อง เราจะเรียก GDownloadUrl ใน map.checksession.php และส่งเซสชัน หากระบบแสดงชื่อผู้ใช้กลับมาได้สำเร็จ เราจะแสดงข้อความต้อนรับต่อผู้ใช้ แสดงแบบฟอร์มเพิ่มสถานที่ และโหลดแผนที่ แบบฟอร์มประกอบด้วยช่องข้อความที่อยู่ แผนที่ และช่องข้อความสำหรับชื่อสถานที่ ละติจูด และลองจิจูด หากผู้ใช้ยังไม่ทราบค่าละติจูด/ลองจิจูดของสถานที่ ก็สามารถแปลงรหัสพิกัดภูมิศาสตร์ได้โดยป้อนที่อยู่ในแบบฟอร์มแล้วกด "ส่ง" ซึ่งจะส่งการเรียกไปยัง GClientGeocoder ของ Maps API ซึ่งจะวางเครื่องหมายบนแผนที่หากพบที่อยู่ และจะป้อนข้อมูลในช่องข้อความละติจูด/ลองจิจูดโดยอัตโนมัติ
เมื่อผู้ใช้พอใจแล้ว ก็สามารถกดปุ่ม "เพิ่มสถานที่" ได้ จากนั้นใน JavaScript เราจะรับค่าสำหรับผู้ใช้ สถานที่ ละติจูด และลองจิจูด แล้วส่งไปยังสคริปต์ 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 ของฟีด และระบุฟังก์ชันเรียกกลับที่จะเรียกใช้เมื่อดาวน์โหลด JSON แล้ว ดูข้อมูลเพิ่มเติมได้ที่นี่
ตัวอย่างโค้ด HTML สำหรับการดำเนินการดังกล่าวมีอยู่ที่นี่: mainmap.htm ภาพหน้าจอแสดงอยู่ด้านล่าง
บทสรุป
หวังว่าตอนนี้คุณจะมีระบบแผนที่ที่ผู้ใช้มีส่วนร่วมเป็นของคุณเองซึ่งทำงานบนเซิร์ฟเวอร์ บทความนี้มีโค้ดพื้นฐานที่จำเป็นสำหรับแง่มุมสำคัญของระบบนี้ แต่ตอนนี้คุณคุ้นเคยกับไลบรารีสเปรดชีต Zend แล้ว คุณควรจะขยายระบบให้ตรงกับความต้องการเฉพาะของคุณได้ หากพบข้อผิดพลาดระหว่างทาง โปรดทราบว่าคุณสามารถใช้คำสั่ง echo ใน PHP หรือ GLog.write() ของ Maps API ใน JavaScript เพื่อแก้ไขข้อบกพร่องได้ และคุณสามารถโพสต์ในฟอรัมนักพัฒนา Maps API หรือ Spreadsheets API เพื่อขอรับความช่วยเหลือเพิ่มเติมได้ทุกเมื่อ