เราได้เคยมีเนื้อหา เกี่ยวกับการดึงข้อมูลจาก 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' => 'lpage@example.com'), array('email' => 'sbrin@example.com'), ), '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' => 'lpage@example.com'), array('email' => 'sbrin@example.com'), ), '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 อื่นๆ เพิ่มเติม เช่น การกำหนดการทำซ้ำ
การกำหนดการแจ้งเตือน เหล่านี้เป็นต้น