2017-05-29

Laravel と Google カレンダーを自動で同期

現在の開発で、とある日付付きのデータが追加/変更/削除されたら Google Calendar へデータを反映させるという機能を追加しました。
正直 Google Calendar API の部分でハマって時間がかかってしまったので、今後のためにもこの記事で Laravel側のプログラムも含めてまとめておこうと思います。


[開発環境]
Laravel: 5.4

[やりたいこと]
日付がついたデータがデータベースに{追加/変更/削除}されたら自動で Google Calendar のイベントを同じく{追加/変更/削除}する。
つまり、DB内のデータと Google Calendar のイベントデータの同期がしたいわけです。
そしてカレンダーをウェブページで表示する。


[手順]
では、大まかな手順です。

1.Google Calendar API を使って読み込み、書き込み、削除ができるよう設定する

2.Laravel に自動実行用のイベント を設定。

3.カレンダーを表示


1.Google Calendar API を使って読み込み、書き込み、削除ができるよう設定する

最初に必要となるのは API と、これから自動的に操作するカレンダーの設定です。
正直、昔のGoogle API それほど複雑ではなく API KEY を取得して URL に含めるだけでOKでしたが、久しぶりに見たらいろんなアプローチの仕方があって困惑してしまいました。
セキュリティ上が大きな原因でしょうから仕方ないといえば仕方ないですね。

ということで、 手順です。

(1) 以下のリンクから Google API でプロジェクトを作成し、サービスアカウントを取得します。

https://console.developers.google.com/permissions/serviceaccounts

やり方は動画を参照してください。
(設定が完了すると json ファイルが自動でダウンロードが開始になるので適当な場所に保存しておいてください。)
↓↓↓



そしてカレンダーAPI を有効に設定しましょう。
↓↓↓



最後にカレンダーの方にカレンダーの書き込み権限を付与します。
そのためにはサービスアカウントを取得した際にダウンロードした json の中に書かれているメールアドレスが必要になるのでテキストエディタなどでファイルを開いてコピーしておきましょう。

"client_email": "********@************************.iam.gserviceaccount.com",

ではカレンダー内での設定です。
↓↓↓



モザイクをかけているので少しわかりづらいかもしれませんが、先ほどダウンロードした json ファイルの中の "client_email" にかかれているメールアドレスを入力しています。
つまり、カレンダーの権限を API に付与しているわけですね。


さて、これで Google API 側の設定は完了です。
次からは Larave 側への設定になります。


2.Laravel に自動実行用のイベント を設定。

準備1: 実行用のイベントを作る前に Google API を操作できるパッケージをインストールしておきましょう。

composer require google/apiclient:^2.0

準備2: ダウンロードした json ファイルを /storage/json/google_api_secret_key.json として設置します。

準備3:カレンダーID を以下のように .env に追加します。

GOOGLE_CALENDAR_ID=****************@group.calendar.google.com

※カレンダー ID の取得は以下の動画を参照してください。



さぁ、ここからは実際にプログラムコードを書いていく作業になります。
(ここでもう作業の 50% は完了しています。)


では、最初に Google API のインスタンスを作成しましょう。
 $key_path = storage_path('app/json/google_api_secret_key.json');  
 putenv('GOOGLE_APPLICATION_CREDENTIALS='. $key_path);  
 $client = new \Google_Client();  
 $client->useApplicationDefaultCredentials();  

次にカレンダー API へアクセスできるよう以下のように設定をします。 
 $client->addScope(\Google_Service_Calendar::CALENDAR);  
 $service = new \Google_Service_Calendar($client);  
はい。これで API へアクセスする準備は整いました。
ここからはカレンダーイベントの追加、編集、削除について説明をしていきます。
※これは実際の実装ではなくイベント操作の基本編です。
実装については「Laravel の Modelイベント」まで読み飛ばしてください。

1.カレンダーイベントの追加

イベントの追加は insert() を使います。
 $calendarId = env('GOOGLE_CALENDAR_ID');  
 $event = new \Google_Service_Calendar_Event([  
   'summary' => 'テストイベントの投稿',  
   'location' => '東京都墨田区押上1丁目1−2',  
   'description' => '東京スカイツリー・バンジージャンプイベント!',  
   'start' => [  
     'dateTime' => '2017-05-16T09:00:00-07:00',  
     'timeZone' => 'Asia/Tokyo',  
   ],  
   'end' => [  
     'dateTime' => '2017-05-16T17:00:00-07:00',  
     'timeZone' => 'Asia/Tokyo',  
   ]  
 ]);  
 $new_event = $service->events->insert($calendarId, $event);  
$calendarId は .env に設定したカレンダーIDになります。
上の例では一日だけのイベントですが2日連続、3日連続などの設定も可能です。
その際は本家のリファレンスページを参照してください。

ちなみに $new_event->getId(); 
とするとイベントIDが取得できるので、このIDをDBなどに保存しておくことでこのイベントの変更、削除をすることができます。


2.カレンダーイベントの変更
 $calendarId = env('GOOGLE_CALENDAR_ID');  
 $event_id = '******************';  
 $event = $service->events->get($calendarId, $event_id);  
 $event->setSummary('変更されたイベント');  
 $service->events->update($calendarId, $event_id, $event);  
さきほどのイベントIDを使って該当するイベントの内容を変更できます。
summary だけでなくその他の情報も変更できます。リファレンスを参照してください。 

※ちなみに変更されたイベント名は以下のように取得します。
 echo $event->getDescription();  

3.カレンダーイベントの削除
 $calendarId = env('GOOGLE_CALENDAR_ID');  
 $event_id = '******************';  
 $service->events->delete($calendarId, $event_id);  
これもカレンダーID と イベントID を指定することで削除が可能です。

さぁ、ここまでがカレンダーイベントを操作する基本になります。
ここからは Laravel の Modelイベントでの実装(つまり実践編)です。

Laravel の Modelイベント

1.Modelの追加イベント

コマンドラインから起動するイベントファイルを作成しましょう。
以下のようにします。

php artisan make:event ItemCreated

これで app/Events フォルダに ItemCreated.php というファイルが作成されているかと思います。

では中身を開いて実際にイベントを追加してみましょう。 
 public function __construct(Item $item)  
 {  
   $calendarId = env('GOOGLE_CALENDAR_ID');  
   $event = new \Google_Service_Calendar_Event([  
     'summary' => $item->summary,  
     'location' => $item->location,  
     'description' => $item->description,  
     'start' => [  
       'dateTime' => $item->date_start,  
       'timeZone' => 'Asia/Tokyo',  
     ],  
     'end' => [  
       'dateTime' => $item->date_end,  
       'timeZone' => 'Asia/Tokyo',  
     ]  
   ]);  
   $service->events->insert($calendarId, $event);  
 }   
これでイベントのプログラム自体は完了ですが、このイベントを起動するプログラムが準備できていません。
しかし、さすがの Laravel です。起動は Model に trait と変数を指定するだけで完了します。
以下のように設定しましょう。
 class Order extends Model  
 {  
   use Notifiable;  
   /**  
    * The event map for the model.  
    *  
    * @var array  
    */  
   protected $events = [  
     'created' => ItemCreated::class  
   ];  
これで、Item テーブルにデータが追加されたら自動で ItemCreated が呼ばれ、その中でイベントがカレンダーに追加されることになります。
このようにイベントを設定しておくとどこでデータを操作をしても忘れずにプログラムを実行してくれるのでとても便利ですね。
 
2.Modelの変更イベント

基本的には追加と代わりませんので簡単な説明だけです。

php artisan make:event ItemUpdated

 public function __construct(Item $item)  
 {  
   $calendarId = env('GOOGLE_CALENDAR_ID');  
   $event = $service->events->get($calendarId, $item->event_id);  
   $event->setSummary('変更されたイベント');  
   $service->events->update($calendarId, $item->event_id, $event);  
 }   
   /**  
    * The event map for the model.  
    *  
    * @var array  
    */  
   protected $events = [  
     'updated' => ItemUpdated::class  
   ];  

3.Modelの変更イベント
 
削除も同じです。
 
php artisan make:event ItemDeleted
 
 public function __construct(Item $item)  
 {  
   $calendarId = env('GOOGLE_CALENDAR_ID');  
   $service->events->delete($calendarId, $item->event_id);   
 }   
   /**  
    * The event map for the model.  
    *  
    * @var array  
    */  
   protected $events = [  
     'deleted' => ItemDeleted::class  
   ];  


はい。
これでModelイベントを利用してカレンダー・イベントを操作してみました。
 
ちなみにもしイベントを好きなタイミングで起動したい場合は以下のようにします。

 event(new ItemCreated($item));  
 event(new ItemUpdated($item));  
 event(new ItemDeleted($item));  



この辺も Lravel のいたれりつくせり感があふれています。
 


3.カレンダーを表示

 
さぁ、せっかくここまでイベントを設定してきたので、自動操作されるカレンダーを実際にウェブページに表示してみましょう。
とはいっても、Google カレンダーでは HTMLタグを提供してくれているのでとても簡単に実装することができます。
 
やりかたは、カレンダーIDを取得したページの「このカレンダーを埋め込む」の項目にある HTMLタグをコピー&ペーストするだけです。

DBにデータを追加/編集/削除するとリアルタイムで(少し時間がかかる場合もあります)変更されると思います。
 
 
以上、今回は Google API を使ってデータを同期する方法でした。
実現するには少し時間がかかるかもしれませんがとても便利な機能なのでぜひチャレンジしてみてください。
 
ではでは! 

0 件のコメント:

コメントを投稿