--- title: Google Calendar api 程式範例 date: 202106 tags: Google Calendar api --- # 2021-06-24 Google Calendar api 程式範例 ## 與 api 綁定 * 將產生的token 存在 $_SESSION中,這樣就不用每次綁定 * credentials.json是[[Google Calendar api 設定]]憑證設定好後,下載到PHP 使用 ``` js // credentials.json { "web": { "client_id": "786168007234-p7a9soquf9v8tmkga8t429gb0vur60o4.apps.googleusercontent.com", "project_id": "ambient-union-317703", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_secret": "vhvTnbJDqh9bQJFd08pDWT6N", "redirect_uris": [ "http://127.0.0.1:20089/linkCalendars.php" ] } } ``` ``` php // linkCalendars.php $calendar = new Calendar(); if (!empty($_GET['code'])) { $calendar->Authenticate($_GET['code']); // 產生 access_token } else { echo "<a href='" . $calendar->GetCalendarAccessUrl() . "'>Google Login</a>"; } // class\calendar.php class Calendar { private $client; function __construct() { $client = new Google_Client(); $client->setApplicationName('Google Calendar API PHP Quickstart'); $client->setAuthConfig('credentials.json'); $client->setAccessType('offline'); $client->setPrompt('select_account consent'); $client->setScopes(array('https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile')); $this->client=$client; $this->google_oauth =new Google_Service_Oauth2($this->client); } // 產生 google api 綁定連結 public function GetCalendarAccessUrl() { // Generate Google calendar access url and login url return $this->client->createAuthUrl(); } # 產生 access_token # 經由 Auth綁定後,會回傳對應code,使用code 產生 access_token # 若沒有傳code,每次呼叫時重新 refresh token public function Authenticate($code=NULL) { if(!empty($code)) { $this->client->authenticate($code); // Authonticate Auth code $access_token = $this->client->getAccessToken(); // Get Access token $refresh_token=$this->client->getRefreshToken(); // Get Refresh token if(!empty($access_token)) { $_SESSION['access_token']=$access_token; } if(!empty($refresh_token)) { $_SESSION['refresh_token']=$refresh_token; } } $this->client->setAccessToken($_SESSION['access_token']); // set the access token // check the access token is expired or not if expired fetcg new one using refresh token if ($this->client->isAccessTokenExpired()) { $access_stoken =$this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken()); } return $this->client; } } ``` ![](https://i.imgur.com/Hmr8toE.gif) ## 顯示 日曆清單 顯示所有日曆清單 ``` php // queryCalendars.php $calendar = new Calendar(); $client=$calendar->Authenticate(); // 憑證 refresh $calendars = $calendar->queryCalendars($client); // google api 取得日曆清單 $calendarview = new CalendarView( $calendars, $client ); $calendarview->showCalendars(); // 顯示日曆清單 // class\calendar.php class Calendar { public static function queryCalendars($client) { $service = new Google_Service_Calendar($client); $calendars = $service->calendarList->listCalendarList()->getItems(); // 篩出 user 擁有的 calendars $owner_calendars = array_filter($calendars, function($calendar) { return $calendar->accessRole === "owner"; // 只顯示自己可以管理的日曆,像是國定假日、農民曆就是外部關聯的,不要抓。 }); return $owner_calendars; } } // class\CalendarView.php class CalendarView { private $calendars; private $client; function __construct( $calendars, $client ) { $this->calendars=$calendars; $this->client =$client; } /** * 顯示 User 所有 calendar */ public function showCalendars() { // 篩出 user 擁有的 calendars $owner_calendars = array_filter($this->calendars, function($calendar) { return $calendar->accessRole === "owner"; }); echo "<table border=1>"; echo " <thead>"; echo " <tr>"; echo " <th>id</th>"; echo " <th>title</th>"; echo " <th>event url</th>"; echo " </tr>"; echo " </thead>"; echo " <tbody>"; foreach ($owner_calendars as $tmp => $calendar) { echo " <tr>"; echo " <td>"; echo $calendar->getId(); echo " </td>"; echo " <td>"; echo $calendar->getSummary(); echo " </td>"; echo " <td>"; echo " <a href='queryCalendars.php?calendarId=". $calendar->getId(). "'>events</a>"; echo " </td>"; echo " </tr>"; } echo " </tbody>"; echo "</table>"; } } ``` ![](https://i.imgur.com/jpO9y7H.gif) ## 顯示 事件清單 ``` php // queryCalendars.php $events = $calendar->queryEvents($client, $_GET['calendarId'], '2021'); $calendarview->showCalendarEvents($events); // class\calendar.php /** * 查詢 Calendar events * @param type $client * @param type $calendar_id 日曆代碼 * @param type $start_year 開始搜尋的年份 * @return type */ public static function queryEvents($client, $calendar_id, $start_year) { $service = new Google_Service_Calendar($client); $query_events = []; // 逐年讀取 events for ($year = $start_year; $year < date('Y', strtotime('+1 years')); $year++) { $start = date(DATE_ATOM, mktime(0, 0, 0, 1, 1, $year)); $end = date(DATE_ATOM, mktime(0, 0, 0, 12, 31, $year)); $params = array( 'singleEvents' => 'true', 'orderBy' => 'startTime', 'timeMin' => $start, 'timeMax' => $end ); try { $query = $service->events->listEvents($calendar_id, $params)->getItems(); } catch (\Exception $e) { return $e->getCode(); } $query_events = array_merge($query_events, $query); // 延遲向 API request 的速度 (單位 second) sleep(1); } return $query_events; } // class\CalendarView.php /** * 顯示 calendar 的所有事件 * @param $events */ public function showCalendarEvents($events) { $result = array_map(function($event) { $_result = [ 'event_id' => $event->getId(), 'title' => $event->getSummary(), 'where' => $event->getLocation(), 'description' => $event->getDescription(), 'startAt' => $event->getStart()->getDate() !== null ? $event->getStart()->getDate() : $event->getStart()->getDateTime(), 'endAt' => $event->getEnd()->getDate() !== null ? $event->getEnd()->getDate() : $event->getEnd()->getDateTime(), '_editeteEventUrl' => "editCalendars.php?calendarId=". $_GET['calendarId']. "&event_id=". $event->getId(), '_deleteEventUrl' => "delCalendars.php?calendarId=". $_GET['calendarId']. "&event_id=". $event->getId(), ]; $_result['startAt'] = date("Y-m-d H:i", strtotime($_result['startAt'])); $_result['endAt'] = date("Y-m-d H:i", strtotime($_result['endAt'])); return $_result; }, $events); krsort($result); echo "<h1>List Calendar's Event</h1>"; echo '<a href="editCalendars.php" target="_blank" >新增日曆事件</a><br>'; echo "<table border=1>"; echo " <thead>"; echo " <tr>"; echo " <th>Title/Description</th>"; echo " <th>Start/End Datetime</th>"; echo " <th>Edit!</th>"; echo " <th>Delete!</th>"; echo " </tr>"; echo " </thead>"; echo " <tbody>"; foreach ($result as $tmp => $event) { echo " <tr>"; echo " <td>"; echo " <div>Title:<br/>". $event['title']. "</div>"; echo " <div>Description:<br/>". nl2br($event['description']). "</div>"; echo " </td>"; echo " <td>"; echo " <div>Start at:<br/>". $event['startAt']. "</div>"; echo " <div>End at:<br/>". $event['endAt']. "</div>"; echo " </td>"; echo " <td><a href='". $event['_editeteEventUrl']. "' target='_blank'>修改</a></td>"; echo " <td><a href='". $event['_deleteEventUrl']. "' target='_blank'>刪除</a></td>"; echo " </tr>"; } echo " </tbody>"; echo "</table>"; } ``` ![](https://i.imgur.com/8TDkgGI.gif) ## 新增&&修改 事件 * 新增&& 修改 ``` php // class\CalendarView.php echo '<a href="editCalendars.php" target="_blank" >新增日曆事件</a><br>'; echo '<a href="editCalendars.php?calendarId=calendarId&event_id=event_id" target="_blank" >修改日曆事件</a><br>'; /** * 顯示 calendar 所屬id的事件 * @param $events */ public function getCalendarEvents( $event, $calendarId="" ) { $result = []; if (empty($calendarId)) { $calendarId="primary"; } // 若未選擇日曆,則帶入預設日曆 if (!empty($event)) { $result = [ 'eventid' => $event->getId(), 'title' => $event->getSummary(), 'where' => $event->getLocation(), 'attendees' => "", 'description' => nl2br($event->getDescription()), 'startAt' => $event->getStart()->getDate() !== null ? $event->getStart()->getDate() : $event->getStart()->getDateTime(), 'endAt' => $event->getEnd()->getDate() !== null ? $event->getEnd()->getDate() : $event->getEnd()->getDateTime(), ]; $result['startAt'] = date("Y-m-d H:i", strtotime($result['startAt'])); $result['endAt'] = date("Y-m-d H:i", strtotime($result['endAt'])); } echo '<form action="saveCalendars.php" method="post">'; echo '<input type="text" name="calendarId" value="'. $calendarId. '">'; echo '<input type="text" name="eventId" value="'. $result['eventid']. '">'; echo '<br/>'; echo '<br/>'; echo '標題<input type="text" name="title" value="'. $result['title']. '"><br/>'; echo '地點<input type="text" name="where" value="'. $result['where']. '"><br/>'; echo '與會者<input type="text" name="attendees" placeholder="example@abc.com" value="'. $result['attendees']. '"><br/>'; echo '敘述<textarea name="description" cols="30" rows="10">'. $result['description']. '</textarea><br/>'; echo '起始時間<input type="text" name="start" id="datetimepicker1" placeholder="click me" value="'. $result['startAt']. '"><br/>'; echo '結束時間<input type="text" name="end" id="datetimepicker2" placeholder="click me" value="'. $result['endAt']. '"><br/>'; echo 'popup 提醒時間<input type="number" name="reminderTime" placeholder="留白會套用預設提醒時間" value="'. $result['id']. '"><br/>'; echo '<input type="submit" value="提交">'; echo '</form>'; } // editCalendars.php $client=$calendar->Authenticate(); $calendars = $calendar->queryCalendars($client); $calendarview = new CalendarView( $calendars, $client ); if(!empty($_GET['calendarId']) && !empty($_GET['event_id'])) { // 若有傳送 event_id,則取出該event 資料 $events = $calendar->queryEvent( $client, $_GET['calendarId'], $_GET['event_id']); } $calendarview->getCalendarEvents( $events, $_GET['calendarId'] ); // 顯示新增日曆畫面 ``` ![](https://i.imgur.com/kgYWpxS.gif) * 保存 先在 saveCalendars.php 整理資料,整理後呼叫google api 保存。 ``` php // saveCalendars.php $client=$calendar->Authenticate(); $calendarId = $_POST['calendarId']; // string $eventId = $_POST['eventId']; // string $title = $_POST['title']; // string $where = $_POST['where']; // string $description = $_POST['description']; // string $startDatetime = $_POST['start']; // string: '2016-05-17 08:00' $endDatetime = $_POST['end']; // string: '2016-05-17 10:00' $attendees = $_POST['attendees']; // string: 'abc@mail.com;xyz@mail.com' (多個 email 以 ; 分隔) $reminderTime = $_POST['reminderTime']; // integers: 50 $result = $calendar->saveEvent($client, $calendarId, $eventId, $title, $where, $description, $attendees, $startDatetime, $endDatetime, $reminderTime); // class\calendar.php public static function saveEvent($client, $calendar_id, $event_id, $title, $where, $description, $attendees, $startAt, $endAt, $reminderTime) { // 若有 event_id 時就做update,不然就insert try { if (!empty($event_id)) { $createdEvent = $service->events->update($calendar_id, $event_id, $event, $optParams); // 更新事件 } else { $createdEvent = $service->events->insert($calendar_id, $event, $optParams); // 寫入事件 } } catch (\Exception $e) { return $e->getCode(); } $eventId = $createdEvent->getId(); // 取得產生後的 event id } ``` ![](https://i.imgur.com/oPMspJu.gif) ## 刪除 事件 ```php // class\CalendarView.php echo '<a href="delCalendars.php?calendarId=calendarId&event_id=event_id" target="_blank" >修改日曆事件</a><br>'; // class\delCalendars.php $result = $calendar->deleteEvent( $client, $_GET['calendarId'], $_GET['event_id']); // class\calendar.php $service = new Google_Service_Calendar($client); $service->events->delete($calendar_id, $event_id); ``` ## 相關連結 * [用 PHP 創建 Google 登錄頁面](https://code.tutsplus.com/tutorials/create-a-google-login-page-in-php--cms-33214) * [Create Google Calendar Event Using PHP - IT Info-Tech](http://www.itinfotech.in/api-integration/create-google-calendar-event-using-php/) * [rz12345/php-google-calendar: PHP implementd Google Calendar API](https://github.com/rz12345/php-google-calendar) * [spatie/laravel-google-calendar: Manage events on a Google Calendar](https://github.com/spatie/laravel-google-calendar)