เราได้เคยมีเนื้อหา เกี่ยวกับการดึงข้อมูลจาก google calendar ด้วย php
สามารถทำทวนเนื้อหาได้ที่บทความ
การดึงข้อมูลจาก google calendar ด้วย php เบื้องต้น http://niik.in/763
https://www.ninenik.com/content.php?arti_id=763 via @ninenik
เนื้อหาตอนต่อไปนี้ เรามาเพิ่มความสามารถให้เราทำการเพิ่มข้อมูลผ่านรูปแบบ
ฟอร์มที่กำหนดเอง ส่งค่าไปบันทึกบน google calendar ซึ่งเป็นเนื้อหาต่อเนื่อง
จากตอนที่กล่าวไปแล้วข้างต้น
การอนุญาตใช้งาน Google Calendar
ในการใช้งาน Google Client Library สำหรับเขียนคำสั่ง API เพื่อเรียกใช้ Google calendar API
จากตอนเที่แล้ว เรากำหนด scope เป็น CALENDAR_READONLY ซึ่งเป็นค่าที่ใช้สำหรับอ่านค่า
ได้อย่างเดียว เหมาะใช้งานในกรณีที่เราไม่ได้ต้องการ เพิ่ม ลบ หรือแก้ไข calendar ผ่าน API
ไฟล์ calendar.php บางส่วน ตอนที่แล้ว
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR_READONLY)
));
แต่กรณีนี้ หรือกรณีที่เราต้องการจัดการเพิ่มเติมมากกว่าการดึงข้อมูลมาแสดงอย่างเดียว เราจำเป็น
ต้องกำหนดค่า scope เป็นค่าที่เหมาะสม สามารถเลือกได้ดังนี้
https://developers.google.com/resources/api-libraries/documentation/calendar/v3/php/latest/class-Google_Service_Calendar.html
- CALENDAR สามารถทำทุกอย่างใน calendar ได้ - CALENDAR_EVENTS สามารถแสดงและแก้ไข event ใน calendar ได้ - CALENDAR_EVENTS_READONLY สามารถแสดงข้อมูล event ทั้งหมดใน calendar ได้ - CALENDAR_READONLY สามารถดูข้อมูลของ calendar ได้อย่างเดียว - CALENDAR_SETTINGS_READONLY สามารถดูการตั้งค่าของ calendar ได้
scope หรือขอบเขตค่าเหล่านี้ เราสามารถนำไปกำหนด เพื่อขอใช้สิทธิการเข้าถึง google calendar ตามความเหมาะสม
สามารถกำหนดได้มากกว่า 1 ค่า ตัวอย่างเช่น เราต้องการ ให้สามารถเพิ่มลบแก้ไข หรือทำทุกอย่างใน calendar ได้
เราก็ให้ทำการปรับค่า scope เป็นประมาณนี้
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR)
));
หรือกรณีต้องการ ดูการตั้งค่าด้วยก็สามารถกำหนดเพิ่มเข้าไปเป็นดังนี้
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR,
Google_Service_Calendar::CALENDAR_SETTINGS_READONLY)
));
อย่างไรก็ตาม การกำหนด scope ที่จะใช้งาน ก็ต้องไปดู คำสั่ง api ที่เราจะใช้ มีเงื่อนไข scope ที่เราต้องกำหนด
เป็นอย่างไร ตามเอกสารอ้างอิง เช่น กรณีการเพิ่ม event หรือกิจกรรมลงใน calendar
ก็จำเป็นต้องเลือกว่าจะใช้อย่างใด อย่างหนึ่งจาก scope ที่กำหนดนี้
Scope
https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/calendar.events
เมื่อเราได้ scope ที่ต้องการแล้ว เราก็ต้องทำการขอสิทธิการเข้าถึงใหม่แทนตัวเดิม โดยให้ทำการลบ
โฟลเดอร์ .credentials ถ้ามีอยู่แล้ว ออกไปก่อน เพื่อสร้างการขอสิทธิใหม่ โดยเริ่มต้นทำการรัน
ไฟล์ calendar.php ผ่าน command line เหมือนเดิม ในขั้นตอนจากบทความแรก http://niik.in/763
ตรงนี้ไม่ขออธิบายซ้ำ ย้อนดูได้ที่ลิ้งค์ที่แนะนำ
ในที่นี้สมมติเราจะจัดการแค่ใน event สำหรับเพิ่ม ลบ แก้ไข event ได้ เราจะใช้ค่า scope เป็น
CALENDAR_EVENTS
ไฟล์ calendar.php
<?php
/** Error reporting */
error_reporting(0);
ini_set('display_errors', FALSE);
ini_set('display_startup_errors', FALSE);
require_once __DIR__ . '/vendor/autoload.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API </title>
<meta charset='utf-8' />
</head>
<body>
<p>Google Calendar API </p>
<?php
define('APPLICATION_NAME', 'CALENDAR-PHP-2021');
define('CREDENTIALS_PATH', __DIR__ . '/.credentials/calendar.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR_EVENTS)
));
// https://developers.google.com/resources/api-libraries/documentation/calendar/v3/php/latest/class-Google_Service_Calendar.html
/*if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}*/
/**
* Returns an authorized API client.
* @return Google_Client the authorized client object
*/
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
$guzzleClient = new \GuzzleHttp\Client(array( 'curl' => array( CURLOPT_SSL_VERIFYPEER => false, ), ));
$client->setHttpClient($guzzleClient);
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
// Store the credentials to disk.
if(!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, json_encode($accessToken));
printf("Credentials saved to %s\n", $credentialsPath);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Expands the home directory alias '~' to the full path.
* @param string $path the path to expand.
* @return string the expanded path.
*/
function expandHomeDirectory($path) {
$homeDirectory = getenv('HOME');
if (empty($homeDirectory)) {
$homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
}
return str_replace('~', realpath($homeDirectory), $path);
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
if (count($results->getItems()) == 0) {
print "No upcoming events found.\n";
} else {
print "Upcoming events:\n";
foreach ($results->getItems() as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
printf("%s (%s)\n", $event->getSummary(), $start);
printf('<br>');
}
}
?>
</body>
</html>
ทดสอบรันผ่านบราวเซอร์

เนื่องจากยังไม่มีข้อมูลใดๆ จึงได้ผลลัพธ์ข้างต้น
การเพิ่มข้อมูล Events ไปยัง Google calendar
ตอนนี้เราสามารถเชื่อมต่อ และรับสิทธิการเข้าถึง google calendar ผ่าน Calendar API
เรียบร้อยแล้ว ขั้นตอนต่อไป เราจะมาทดสอบการเพิ่มข้อมูล event เข้าไปใน calendar โดยให้เราสร้าง
ไฟล์ชื่อ add_event.php และใช้รูปแบบโค้ดคล้ายกับ calendar.php แต่ปรับแต่งเล็กน้อย ดังนี้
ไฟล์ add_event.php
<?php
/** Error reporting */
error_reporting(0);
ini_set('display_errors', FALSE);
ini_set('display_startup_errors', FALSE);
require_once __DIR__ . '/vendor/autoload.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API </title>
<meta charset='utf-8' />
</head>
<body>
<p>Add new Event</p>
<?php
define('APPLICATION_NAME', 'CALENDAR-PHP-2021');
define('CREDENTIALS_PATH', __DIR__ . '/.credentials/calendar.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR_EVENTS)
));
// https://developers.google.com/resources/api-libraries/documentation/calendar/v3/php/latest/class-Google_Service_Calendar.html
/*if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}*/
/**
* Returns an authorized API client.
* @return Google_Client the authorized client object
*/
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
$guzzleClient = new \GuzzleHttp\Client(array( 'curl' => array( CURLOPT_SSL_VERIFYPEER => false, ), ));
$client->setHttpClient($guzzleClient);
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
// Store the credentials to disk.
if(!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, json_encode($accessToken));
printf("Credentials saved to %s\n", $credentialsPath);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Expands the home directory alias '~' to the full path.
* @param string $path the path to expand.
* @return string the expanded path.
*/
function expandHomeDirectory($path) {
$homeDirectory = getenv('HOME');
if (empty($homeDirectory)) {
$homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
}
return str_replace('~', realpath($homeDirectory), $path);
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
?>
</body>
</html>
ไฟล์โค้ดนี้ เราตัดส่วนของการแสดงรายการ event ของ calendar ออกไป แต่ยังไม่เพิ่มส่วนของคำสั่งการ
เพิ่ม event ใหม่เข้าไป
ให้เราดูตัวอย่างการเพิ่มข้อมูลใหม่จากหน้า
ส่วนของโค้ดตัวอย่างการเพิ่มข้อมูล
$event = new Google_Service_Calendar_Event(array(
'summary' => 'Google I/O 2015',
'location' => '800 Howard St., San Francisco, CA 94103',
'description' => 'A chance to hear more about Google\'s developer products.',
'start' => array(
'dateTime' => '2015-05-28T09:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
),
'end' => array(
'dateTime' => '2015-05-28T17:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
),
'recurrence' => array(
'RRULE:FREQ=DAILY;COUNT=2'
),
'attendees' => array(
array('email' => '[email protected]'),
array('email' => '[email protected]'),
),
'reminders' => array(
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 24 * 60),
array('method' => 'popup', 'minutes' => 10),
),
),
));
$calendarId = 'primary';
$event = $service->events->insert($calendarId, $event);
printf('Event created: %s', $event->htmlLink);
ขอแยกออกมาให้เป็นภาพ และกำหนดข้อมูลสมมติ สำหรับทดสอบ โดยเปลี่ยน
ปีเป็น 2021 และ timeZone เป็น Asia/Bangkok
/////////// ส่วนของการเพิ่ม Event
// ตัวแปรโครงสร้าง parameter สำหรับสร้าง event
$event_data = array(
'summary' => 'Google I/O 2021', // หัวเรื่อง
'location' => '800 Howard St., San Francisco, CA 94103', // สถานที่
'description' => 'A chance to hear more about Google\'s developer products.', // รายละเอียด
'start' => array( // วันที่เวลาเริ่มต้น
'dateTime' => '2021-05-28T09:00:00-07:00',
'timeZone' => 'Asia/Bangkok',
),
'end' => array( // วันที่เวลาสิ้นสุด
'dateTime' => '2021-05-28T17:00:00-07:00',
'timeZone' => 'Asia/Bangkok',
),
'recurrence' => array( // การทำซ้ำ
'RRULE:FREQ=DAILY;COUNT=2'
),
'attendees' => array( // ผู้เข้าร่วม อีเมล
array('email' => '[email protected]'),
array('email' => '[email protected]'),
),
'reminders' => array( // การแจ้งเตือน
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 24 * 60),
array('method' => 'popup', 'minutes' => 10),
),
),
);
$event = new Google_Service_Calendar_Event($event_data); // สร้าง event object
$calendarId = 'primary'; // calendar หลัก
$event = $service->events->insert($calendarId, $event); // ทำคำสั่งเพิ่มข้อมูล
printf('Event created: %s', $event->htmlLink); // หากเพิ่มข้อมูลสำเร็จ จะได้ค่า ลิ้งค์
นำโค้ดตัวอย่างข้างต้นไปต่อท้ายในไฟล์ add_event.php แล้วรันผ่านบราวเซอร์
ผลลัพธ์ที่ได้

จะเห็นว่าคำสั่งข้างต้น ทำการสร้าง event ให้เราสำเร็จ พร้อมกับมี url ของ event ที่เพิ่งสร้าง ที่จะพา
เราไปยังหน้า event ใน google calendar ตามรูปตัวอย่าง

จากรูปคือข้อมูลตัวอย่างที่ถูกเพิ่มไปใน google calendar
ถ้าเรากลับมาเปิดไฟล์ calendar.php ก็จะแสดงข้อมูล event ที่ถูกเพิ่มเข้ามาล่าสุด 2 รายการ ของวันที่
28 และ 29

ทั้งนี้มีส่วนของการกำหนดการทำซ้ำใน parameter ด้วย นั่นคือค่า
'recurrence' => array( // การทำซ้ำ
'RRULE:FREQ=DAILY;COUNT=2'
),
สังเกตรูปแบบการกำหนด FREQ คือความถึ่ กำหนดเป็น DAILY และ จำนวนวัน COUNT กำหนดเป็น 2
ดังนั้นด้วยรูปแบบการกำหนดค่าการทำซ้ำ จึงมี event เพิ่มมาสองวันนั่นเอง
การลบข้อมูล Events ใน Google calendar
สำหรับการลบข้อมูล Event มีรูปแบบคำสั่งที่ง่าย ดังนี้
$service->events->delete('primary', 'eventId');
parameter ที่เราต้องส่งก็คือ calendarID กับ eventId
ในไฟล์ calendar.php เราวนลูปแสดงรายการแล้ว เราจะลองเพิ่มลิ้งค์ปุ่มสำหรับส่งค่า eventId สำหรับ
ใช้ในการลบเข้าไป และเพิ่มส่วนของคำสั่งสำหรับลบข้อมูลเข้าไปด้วย โดยปรับโค้ดเล็กน้อยดังนี้
ไฟล์ calendar.php (บางส่วน)
// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c'),
);
// ส่วนของการลบข้อมูล
if(isset($_GET['eventId']) && $_GET['eventId']!=""){
$eventId = $_GET['eventId'];
$service->events->delete($calendarId, $eventId);
header("Location:calendar.php");
exit;
}
// ส่วนของการดึงข้อมูลมาแสดง
$results = $service->events->listEvents($calendarId, $optParams);
if (count($results->getItems()) == 0) {
print "No upcoming events found.\n";
} else {
print "Upcoming events:\n";
foreach ($results->getItems() as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
printf("%s (%s)\n", $event->getSummary(), $start);
print("<a href='?eventId=".$event->getId()."'>Delete</a>");
printf('<br>');
}
}
ทดสอบรันก็จะได้ผลลัพธ์ประมาณนี้

เราลองทดสอบกดลบรายการล่างสุด

รายการล่างสุดก็จะถูกลบ เหลือแค่รายการเดียวด้านบน ตอนนี้ลบออกให้หมดไปก่อนได้เลย
การประยุกต์การเพิ่ม Event ใน Google calendar ผ่าน Calendar API อย่างง่าย
จากเดิมเราทดสอบการเพิ่มข้อมูล โดยใช้ค่าที่กำหนดตายตัว เพื่อดูรุปแบบการทำงานในไฟล์
add_event.php
ต่อไป เราจะลองส่งค่าจากฟอร์มที่เราสร้างขึ้นมา เพื่อบันทึกผ่าน api ไปยัง calendar โดยในที่นี้
จะใช้รูปแบบอย่างง่าย และตัด parameter บางส่วนออกไป ปรับไฟล์ในส่วนของ add_event.php
บางส่วนเป็นดังนี้
ไฟล์ add_event.php (บางส่วน)
/////////// ส่วนของการเพิ่ม Event
// ตัวแปรโครงสร้าง parameter สำหรับสร้าง event
$summary = $_POST['summary'];
$description = $_POST['description'];
$start = $_POST['start'];
$end = $_POST['end'];
// ตรวจสอบอย่างง่าย ว่ามีค่าส่งมาหรือไม่ มีค่าส่งมาจึงจะทำการเพิ่มข้อมูล
if($summary != "" && $description !="" && $start !="" && $end !=""){
$event_data = array(
'summary' => $summary, // หัวเรื่อง
'description' => $description, // รายละเอียด
'start' => array( // วันที่เวลาเริ่มต้น
'date' => $start,
'timeZone' => 'Asia/Bangkok',
),
'end' => array( // วันที่เวลาสิ้นสุด
'date' => $end,
'timeZone' => 'Asia/Bangkok',
),
);
$event = new Google_Service_Calendar_Event($event_data); // สร้าง event object
$calendarId = 'primary'; // calendar หลัก
$event = $service->events->insert($calendarId, $event); // ทำคำสั่งเพิ่มข้อมูล
printf('Event created: %s', $event->htmlLink); // หากเพิ่มข้อมูลสำเร็จ จะได้ค่า ลิ้งค์
}
echo "<br>";
echo "<a href='calendar.php'>Back to Form</a>";
ต่อไปในไฟล์ calendar.php เราจะสร้างฟอร์มอย่างง่ายจากในไฟล์นี้ โดยเพิ่มโค้ดไปด้านล่างสุดของไฟล์
ไฟล์ calendar.php (บางส่วนด้านล่าง)
<hr> <form action="add_event.php" method="post"> Summary:<input type="text" name="summary"><br> Description:<textarea name="description" rows="3" cols="50"></textarea><br> Start Date:<input type="date" name="start"><br> End Date:<input type="date" name="end"><br> <button type="submit">Send</button> </form>
ตัวอย่างหน้าผลลัพธ์

เราทดสอบกรอกข้อมูล ประมาณนี้ลงไป

จากนั้นกดส่งข้อมูล หากไม่มีอะไรผิดพลาดผลลัพธ์ในไฟล์ add_event.php จะเป็นดังนี้

เพิ่มกิจกรรมสำเร็จ ข้อมูลใน google calendar ก็จะประมาณนี้

เรากดลิ้งค์กลับไปที่หน้า calendar.php ก็จะแสดงรายการล่าสุดที่เราเพิ่งเพิ่มเข้าไป

แนวทางการประยุกต์ข้างต้น เป็นรูปแบบอย่างง่าย ดังนั้น หากเราต้องการให้สามารถจัดการหรือ
กำหนดรูปแบบได้มากขึ้น ให้ทำความเข้าใจกับ parameter อื่นๆ เพิ่มเติม เช่น การกำหนดการทำซ้ำ
การกำหนดการแจ้งเตือน เหล่านี้เป็นต้น