TokyoFacebookTwitterHatenaPocket予定の管理はGoogleカレンダーが便利。独自のインターフェイスを持ったカレンダーサービスが作りたい。APIを使ってみるといいかもしれません。APIを扱う方法を紹介します。カレンダーアプリを構築し、ユーザーが新しいカレンダーを作成したり、イベントを追加したり、Googleカレンダーと同期したりできるようにします。この記事に沿って作業する場合は、Homesteadをセットアップするとアプリの実行環境を簡単に用意できるのでおすすめです。Consoleで新たなプロジェクトを作成します。APIs(APIを有効にして管理しましょう)」をクリックします。APIを選択し有効にします。APIのページに戻り「Credentials(認証情報)」のリンクをクリックします。ID)」を選択します。screen(同意画面を設定)」をクリックして設定します。任意のメールアドレス、サービス名をそれぞれ選択、入力し「save(保存)」をクリックします。アプリケーション)」を作成します。クライアントIDとクライアントシークレットを取得できます。アプリの構築Composer経由でLaravelを使用します。kalendaryoプロジェクトのディレクトリとしてkalendaryoという新たなフォルダーが作成されます。そのほかの依存オブジェクトをインストールします。APIとやりとりします。APIを使用してGoogleカレンダーを操作します。アプリの設定プロジェクトディレクトリのルートにある.envファイルを開き、必要な項目を以下のように追加します。APP_TIMEZONE、GOOGLE_CLIENT_ID、GOOGLE_CLIENT_SECRET、GOOGLE_REDIRECT_URLです。APP_TIMEZONEについては、PHPタイムゾーンのページから任意の値を使用できます。データベースの項目については、新たなMySQLデータベースを作成し、データベース名をDB_DATABASEの値に使用します。DB_USERNAMEとDB_PASSWORDはデータベースにログインするための認証情報です。secretを利用できます。GOOGLE_REDIRECT_URLの値をGoogleコンソールで前もって取得しておいた認証情報に置き換えます。GOOGLE_SCOPESはアプリで必要となる権限です。同意画面に表示されたものをここに入れます。ユーザーは、アプリが特定のデータにアクセスすることに同意する必要があります。説明したような情報がどこにあるか分からなければ、oauthplaygroundで調べられます。APIを選択しドロップダウンに表示されるURLがその権限です。emailとprofileは単にhttps://www.googleapis.com/auth/userinfo.emailとhttps://www.googleapis.com/auth/userinfo.profileを省略したものです。あとで配列にコンバートするので、それぞれの権限はカンマで分けておきます。Googleクライアントのサービスコンテナを作成する次に、Googleクライアントのサービスコンテナの説明をします。app/Googl.phpファイルを作成し以下を追加します。type(アクセス種別)をセットしています。これらの値はすべて、前に作成しておいた.envファイルから読み込みます。すべてセットしたら、新たなインスタンスを返します。あとでclientメソッドを呼び出しGoogleクライアントを初期化します。ルーティングapp/Http/routes.phpファイルを開き、アプリ内の各ページへのルーティングを追加します。'HomeController@login');上のコードでadminと呼ばれる独自のルーティングミドルウェアを使用していますが、あとで作成します。ルーティンググループ内でミドルウェアを使うと、グループ内のすべてのルートに対しミドルウェアが有効になります。});コールバック関数内には、そのグルーブに属する各ルートがあります。これらは一目で内容が分かります。POSTリクエストに応じるルートは書き込み処理のために使用します。GETルートは読み取り専用です。'AdminController@logout');Adminルーティングミドルウェア先に述べたように、ルーティングミドルウェアは特定のルートへのアクセスに対してコードを実行するために使用されます。adminミドルウェアの場合は、ユーザーが現在ログインしているかどうかを確認するために使用されます。app/Http/Middleware/AdminMiddleware.phpにadminミドルウェアを作成し、以下を追加します。}}ほとんどのミドルウェアは共通点を1つ持っています。リクエストを処理するためのhandleメソッドがあるということです。これはルーティングに応答するどのメソッドよりも先に実行されます。メソッド内でuserが現在のセッションにセット済みかチェックします。セット済みであれば、リクエストの処理に進みます。$next($request);}セット済みでなければ、ユーザーをホームページにリダイレクトし、セッションに対しログインが必要だというメッセージを渡します。);app/Http/Kernel.phpファイル内の$routeMiddleware配列の下に以下を追加してミドルウェアを使用可能にします。\App\Http\Middleware\AdminMiddleware::classデータベースアプリはuser、calendar、eventという3つのテーブルを使用します。リポジトリからマイグレーションデータをコピーし、プロジェクトの同じパスに貼り付ければ、時間を短縮できます。migrateを実行するとデータベースにテーブルが作成されます。そのあと、User.php、Calendar.php、Event.phpのコンテンツをappディレクトリにコピーします。この3つのファイルはあとでデータベースとやりとりする際のモデルになります。ホームページapp/Http/Controllers/HomeController.phpファイルを作成し、以下を追加します。}}上のコードを細かく説明すると、最初にログインビューを返すindexメソッドがあります。view('login');}resources/views/login.blade.phpファイル内でログインビューを作成します。Google</button></form>@stopログインビューはグーグルにログインするためのログインボタンがついているフォームです。このビューはデフォルトテンプレート(resources/views/layouts/default.blade.php)を継承していて、以下が含まれています。CSSは表示を整えるために使用されています。スタイルシートはpublic/assetsディレクトリに保存します。手動でインストールするか、あるいはBowerPHPのような便利なツールも利用できます。@yield('content')部分がログインフォームを表示する場所です。partials.alertもインクルードしています。resources/views/partials/alert.blade.phpファイルに定義してあり、ユーザーに対してメッセージやフォームのバリデーションエラーを表示するために使用します。</div>@endifHomeControllerに戻ります。次はloginメソッドです。Googleクライアントのサービスコンテナを使用できるようにタイプヒンティングを使用します。Userモデルについても同様です。$user){...}loginメソッド内で、Googleクライアントの新たなインスタンスを生成し、コードがクエリパラメーターとしてURLに渡されているか確認します。過去のプロジェクトでOAuthを実装したことがない人のために動作を説明すると、ユーザーはサービスのログインページへと続くリンクをクリックしなければなりません。今回の場合はグーグルです。ユーザーはグーグルのログインページにリダイレクトされます。ログイン後、ユーザーは認証を求められます。ユーザーが同意すれば、ユニークなコードをURLに付加したWebサイトにリダイレクトします。このコードはアクセストークンを取得するために使用します。アクセストークンを使用することで、アプリはAPIにリクエストを出せます。ここで確認しているコードはアクセストークンと交換するために使用するコードです。コードが存在しなければ、ユーザーをグーグルのログインページにリダイレクトします。redirect($auth_url);}コードが存在すれば、そのコードを使用してユーザーを認証します。$client->authenticate($request->get('code'));ユーザーの認証によって、アクセストークンの取得とGoogle+サービスに対するリクエストの初期化が可能になります。\Google_Service_Plus($client);このあと、現在ログイン中のユーザーを取得し、ユーザー情報を取り出します。nameユーザーがデータベース上にすでに存在するか確認します。$email)->first();ユーザーが存在しなければ、ユーザーを新規作成しエントリをデータベースに保存します。ユーザーのデフォルトカレンダーを作成します。以下は初期設定のGoogleカレンダーです。コピーを作成して、Googleカレンダーサービスとデータの同期を開始すればイベント(予約)がコンテナを持てるようにします。$calendar->save();}ユーザーがすでに存在していれば、値を$user_idに割り当て、ユーザーをセッションにセットします。$has_user->id;ユーザーの詳細をセッションに保存します。]]);最後にユーザーを管理ダッシュボードページにリダイレクトします。in.']);管理ページ続いて、app/Http/Controllers/AdminController.phpファイルに管理ページのコントローラーを作成します。}}上のコードを細かく説明します。コントローラー内で$client変数はコンストラクタで初期化したGoogleクライアントへの参照を保存します。この方法により、Googleクライアントが必要になるたびに初期化しなくて良くなります。$this->client->setAccessToken(session('user.token'));}indexメソッドは管理ダッシュボード(resources/views/admin/dashboard.blade.php)ビューを返します。view('admin.dashboard');}管理ダッシュボードは各ページへのリンクを含み、ユーザーはリンク先でさまざまな操作ができます。href="/logout">Logout</a></li></ul>@stopこのビューは以下の管理レイアウト(resources/views/layouts/admin.blade.php)を継承しています。@yield('create_event_script')</body></html>上のコードで、メインコンテンツのほかにいくつかのテンプレートをyieldしています。これらのテンプレートは別のビューから渡されます。ビューがyieldしたセクションを定義していなければ、コードはなにも返しません。カレンダーの作成AdminControllerに戻ります。以下はカレンダーを新規作成するためのビューを返すメソッドです。view('admin.create_calendar');}作成したカレンダービューは、カレンダーのタイトルを入力するフォームを含みます。CSRF(クロスサイトリクエストフォージェリ)の防止に使用される、隠れたフィールドがあります。Calendar</button></form>@stopフォームを送信したらdoCreateCalendarメソッドが呼び出されます。メソッド内で、タイトルフィールドに値が与えられているか、またその値が4文字以上あるかを検証します。'required|min:4']);Googleカレンダークライアントを初期化します。\Google_Service_Calendar($this->client);新たなカレンダーを作成します。ユーザーが入力したタイトルをセットし、アプリのデフォルトタイムゾーンをセットします。$cal->calendars->insert($google_calendar);カレンダーのIDを取得します。$created_calendar->getId();新たに作成したカレンダーをデータベースに保存します。$calendar_id;$calendar->save();ユーザーをカレンダー新規作成ページにリダイレクトします。次は、イベントを新規作成するビューを返すメソッドです。ここでは、ユーザーによって作成済みの複数のカレンダーを渡します。ユーザーがイベントをどのカレンダーに追加するか選ぶ必要があるからです。datetimepickerといったスタイルやスクリプトを含みます。DOMイベントをリッスンするためにjQueryを使用します。datetimepickerを使用します。フォーム内には、イベントのタイトルを入力するためのフィールド、イベントを追加するカレンダーを選択するためのフィールド、開始日時と終了日時、参加者の名前とメールアドレスを入力するためのフィールドがあります。フォームの下には、参加者の列に使用するhandlebarsテンプレートがあります。id="attendees">...</div>)。}}"></script>@stop上のテンプレートではcreate_event.jsファイルもインクルードしています。このファイルの役割は日付けフィールドを日時入力支援機能に変換し、参加者のメールアドレスのテキストフィールドでblurイベントをリッスンすることです。blurイベントが発生し、ユーザーが参加者名とメールアドレスを列に入力していれば、新たな列を生成しユーザーが新たな参加者を入力できるようにします。}});次は、イベント作成フォームの送信時に実行されるメソッドです。...}メソッド内でフォームを検証しフィールドからデータを取得します。$request->input('datetime_end');開始および終了日時を日付けオブジェクトにコンバートすることで、容易にフォーマットできるようにします。$end);新たなGoogleカレンダーのイベントを作成し、ユーザーが入力したタイトルをサマリーにセットします。\Google_Service_Calendar_Event();$event->setSummary($title);開始および終了日時をセットします。APIは、日付けと時間がATOM時間表記にフォーマットされていることを前提としているので注意してください。そのため、Carbonが提供するtoAtomString()メソッドを使用して$start_datetimeと$end_datetimeをフォーマットします。\Google_Service_Calendar_EventDateTime();$end->setDateTime($end_datetime->toAtomString());$event->setEnd($end);ユーザーが参加者を追加したか確認します。...}追加していれば、参加者に変数を割り当てます。$request->input('attendee_email');参加者それぞれについてループ処理し、ユーザーが名前とメールアドレスの両方を入力していれば、Googleカレンダーに新たなイベント参加者を作成し、名前とメールアドレスをセットします。作成した参加者を$attendees配列に追加します。}}各参加者のループ処理が終了したら、$attendees配列をイベントの参加者に設定します。$attendees;イベントをGoogleカレンダーに保存します。$event);イベントをデータベースにも保存します。$end_datetime->toDateTimeString();$evt->save();イベント作成ページにリダイレクトします。次はカレンダーを同期させるためのビュー(resources/views/admin/sync_calendar.blade.php)を返す関数です。ユーザーが作成したカレンダーをビューのデータとして渡します。$page_data);}以下はadmin.sync_calendarビューのコードで、ユーザーは同期するカレンダーを選択できます。送信後にコードが処理する内容は、データベースにまだ追加されていないイベントの追加、キャンセルされたイベントの削除、最後の同期から変更された内容の更新です。Calendar</button></form>@stopユーザーがカレンダー同期フォームを送信したらdoSyncCalendarメソッドが実行されます。...}関数内で、データベースにあるカレンダーを見つけます。$calendar->calendar_id;Googleカレンダーサービスの新たなインスタンスを作成し、IDに基づきカレンダーとカレンダーのタイムゾーンを取得します。イベント日時が使用しているタイムゾーンにセットします。この方法を使えば、アプリが使用するタイムゾーンへ容易にコンバートできます。$g_calendar->getTimeZone();ユーザーが選択したカレンダーに属するイベントのIDを取得します。イベントが追加済みか確認するために使用します。ここから、イベントをどう処理するか判断していきます。イベントがデータベース中にあり、さらにキャンセルされていない状態なら、更新が必要です。なければデータベースから削除します。データベース中になければ追加する必要があります。->toArray();最初の同期のためにデフォルトフィルターを指定します。showDeletedオプションを使用すると削除されたイベントを返します。timeMinオプションを使用するとリクエストに使用される日時の下限を指定できるので、過去のイベントが返されなくなります。->toAtomString()];Googleカレンダーと同期するために、同期トークンを使用します。カレンダーに変更がある(例:イベントの追加)たびに同期トークンも変わります。データベースにトークンを保存しておく必要があります。Googleのサーバーにあるトークンが、持っているトークンと同じなら変更はありません。トークンが異なるときにのみ、更新します。更新後に、データベース中のトークンも更新する必要があります。同期トークンが空でなければ、デフォルトフィルターの代わりに使用します。更新された、あるいは追加されたイベントだけを返せます。];}イベントを取り出します。$params);次は、ユーザーが選択したカレンダーのすべての更新を取り出すまで停止しない無限ループです。...}無限ループ内で、APIによって返されるイベントをループ処理し、関連するデータを取り出します。...}イベントの状態を確認します。キャンセルされていれば、イベントをデータベースから削除します。}}イベントがキャンセルされていなければ、イベントの開始および終了日時を取り出しアプリのタイムゾーンにコンバートします。H:i:s');イベントIDがイベントID配列中に見つかれば、そのイベントは更新済みであることを意味するので、データベースも更新します。$event->save();}配列中になければ、そのイベントは新たなイベントなので、データベースに新たなエントリを追加します。$event->save();}イベントをループし終ったら、次のページのためのページトークンを取得します。このトークンは先の同期トークンとは別なので注意してください。ページトークンはページ繰りのためだけに使用されるものです。ここでは単に、現在の結果セットにまだページがあるかを確認しています。$googlecalendar_events->getNextPageToken();次のページがあれば、ページを次のリクエスト用のpageTokenとしてセットし、イベント取り出しのリクエストに進みます。$params);}次のページがなければ、すべての結果を取得済みなので、次の同期トークンを取得し使用してデータベースを更新します。ここで、無限ループを抜け出します。loop}カレンダー同期ページにリダイレクトし、ユーザーに対してカレンダーが同期されたことを伝えます。次はユーザーが同期を完了したすべてのイベントを表示するメソッドです。$page_data);}このイベントビュー(resources/views/admin/events.blade.php)は以下を含みます。</tbody></table>@endif@stop@stopログアウト最後に、logoutメソッドがあります。管理ダッシュボードにあるログアウトのリンクをユーザーがクリックすると実行されるメソッドです。すべてのセッションデータを削除し、ユーザーをホームページにリダイレクトします。out']);}最後に以上です。APIを組み込んだPHPアプリの構築方法を見てきました。その中で、PHPを使ってGoogleカレンダーを操作する方法も説明しました。Anchetaフィリピン出身のWeb開発者です。Web構築に情熱を注ぎ、ノウハウをブログで公開しています。アニメとビデオゲームも大好き。