BLOG

ブログ( EdTech, web制作, DX )

PHPを使ってGoogleカレンダーにフォームから予定を登録してみる

こんにちは。
システムエンジニアの今井です。

今回ですが、PHPを使ってGoogleカレンダーの予定をフォームで入力して登録する処理を行ってみたいと思います。

1.今回の処理の完成図

■用意するフォーム

ws000104
■項目の説明
・終日:
=>「はい」を選択すると日付単位でカレンダーを登録します。
=>「いいえ」を選択すると時間単位でカレンダーを登録します。
・開始時間:
=>予定開始日時を入力します。「終日」で「はい」を選択しているときは時間は無視されます。
・終了時間:
=>予定終了日時を入力します。「終日」で「はい」を選択しているときは時間は無視されます。
・件名:
=>カレンダーの件名の箇所に登録される情報です。
・本文:
=>カレンダーの説明の箇所に登録される情報です。

■動作結果
終日は「いいえ」で4月27日の15:00~18:00で登録するとカレンダー上にはこのように登録されます。ws000105

では、上記の動きができるプログラムを説明したいと思います。
 
 

2.用意するもの

・Googleアカウント
・サービスアカウントキー
・google-api-php-clientプログラム
※Googleアカウントの取得方法はここでは省略させていただきます。
 
 

3.サービスアカウントキー

前回のブログでもサービスアカウントキーの取得方法を説明しましたが、前回からGoogleの画面が多少変化しましたので改めて説明します。
 
①:GoogleDeveloperConsoleページにアクセスします。
https://code.google.com/apis/console/

②:「プロジェクトの作成」をクリックします。ws000106

③:「hoge」という名前でプロジェクトを作成します。ws000107

④:作成が完了するとライブラリの画面へ移動します。ws000108

⑤:検索窓に「calendar」と入力すると、「CalendarAPI」が表示されますのでクリックします。ws000109

⑥:「有効にする」をクリックします。ws000110

⑦:有効になった後、左メニューの「認証情報」をクリックします。
ws000111

⑧:「認証情報を作成」から「サービスアカウントキー」をクリックします。ws000112

⑨:「サービスアカウント」に「新しいサービスアカウント」を選択し、「サービスアカウント名」に「google-calendar-test」を入力します。「キーのタイプ」は「JSON]を選択して、「作成」をクリックします。
※「サービスアカウントID」は自動入力されます。ws000114

⑩:「サービスアカウントに役割が割り当てられていません」と表示されますが、「役割なしで作成」をクリックします。その後jsonファイルがダウンロードされるので、そのファイルをPCに保存します。ws000115

以上で、サービスアカウントキーの取得が完了しました。
 
 

4.企業用のGoogleアカウントを利用している場合

企業アカウントでGoogleを利用している場合、デフォルトのままではプログラムからGoogleカレンダーに書き込みができません。
その場合、以下の手順で許可します。
ただし、社内ポリシーで以下の作業自体ができない時は残念ですが、個人用Googleアカウントで作業を行ってください。
個人用Googleアカウントを使う場合は「4.企業用のGoogleアカウントを利用している場合」の章を飛ばして「5.google-api-php-clientプログラム取得方法」へ進んでください。
 
①:管理者ユーザでGoogleアカウント管理画面にログインします。
 ログインURLは各々の組織のログインURLでログインしてください。
 
②:管理コンソール画面から「アプリ」をクリックします。ws000116

③:「G Suite」をクリックします。ws000117

④:「カレンダー」をクリックします。ws000118

⑤:「共有設定」の「メインカレンダーの外部共有オプション」で「すべての情報を共有し、カレンダーを管理できます。」にチェックを入れて、「保存」をクリックします。ws000119
※保存を設定しても、すぐには反映されない場合があります。詳しくは「6.Googleカレンダーの準備」の④の部分をお読みください。

以上が、企業用のGoogleアカウントを設定している場合の設定になります。
 
 

5.google-api-php-clientプログラム取得方法

Googleカレンダーからサービスアカウント方式でデータを取得するため、google-api-php-clientというライブラリのバージョン1.1.7を使います。
①:以下URLを開きます。
https://github.com/google/google-api-php-client

②:releasesという箇所をクリックします。16

③:1.1.7の「Source code(zip)」をクリックしてzipファイルをダウンロードします。17

ダウンロードしたzipファイルはローカルPCに保存しておきます。
※後ほどこのzipファイルを使います。
 
 

6.Googleカレンダーの準備

プログラムからデータを書き込みたいカレンダーに対して先ほどダウンロードしたjsonファイルのサービスアカウントキーを登録する必要があります。
 
①:「3.サービスアカウントキー取得方法」でダウンロードしたjsonファイルをテキストエディタで開きます。
※client_emailの値を覚えておきます。
 
②:Googleカレンダーを開きます。
 
③:「マイカレンダー」から「新しいカレンダー作成」をクリックします。
9

④:新しいカレンダーに以下の項目を入力して、「カレンダーを作成」を押します。
・「カレンダー名」に任意の値を入れます。(ここではhogeとしています)
・「ユーザ」に①で取得したclient_emailの値を入れます。
・「権限の設定」で「変更および共有の管理権限」を選んで「ユーザ追加」を押します。
 ※ここで「変更および共有の管理権限」が選択できない場合は「4.企業用のGoogleアカウントを利用している場合」の⑤の設定がまだ反映されていない可能性があります。その時は、しばらくまった後再度お試しください。

ws000120

⑤:次にこのカレンダーのIDを控えます。作成された「hoge」カレンダーの▼をクリックして「カレンダー設定」をクリックします。ws000122

⑥:「カレンダーのアドレス」行の「カレンダーID」を控えておきます。ws000123

以上でGoogleカレンダー側の設定は終了です。
 
 

7.フォームからGoogleカレンダーに書き込みができる処理を作成してみます

 
①:サーバ上に今回のプログラムを設置するディレクトリを作成します。
サーバ上のDocumentRoot上にgooglecalendarというディレクトリを作成します。
 
②:googlecalendarディレクトリの下にgoogle-api-php-clientというディレクトリを作成します。
 
③:「5.google-api-php-clientプログラム取得方法」の③でダウンロードしたファイルをデスクトップに解凍します。
 
④:デスクトップに解凍してできたディレクトリの中にあるsrcというディレクトリを②のgoogle-api-php-clientディレクトリの下に入れます。
 
⑤:②のgoogle-api-php-clientディレクトリの下にkeyというディレクトリを作成します。
 
⑥:⑤で作成したkeyというディレクトリの下に3.サービスアカウントキーの⑩で取得したjsonファイルを置きます。
 
⑦:googlecalendarディレクトリ直下にフォームHTMLを用意します。名前はform.phpとします。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width">
<title>Googleカレンダー登録用フォーム</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"/>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
    <div class="col-xs-1">
    </div>
    <div class="col-xs-11">
        <h1>Googleカレンダー登録用フォーム</h1>
        <form method="post">
        <div class="row">
            <div class="col-xs-2"><label>終日:</label></div>
            <div class="col-xs-5 form-inline">
                <select class="form-control" name="all_day">
                    <option value="0">いいえ</option>
                    <option value="1">はい</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>開始時間:</label></div>
            <div class="col-xs-5 form-inline">
                <input class="form-control input-sm" type="text" name="start_day" value=""/>
                <input class="form-control input-sm" type="text" name="start_time" value=""/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>終了時間:</label></div>
            <div class="col-xs-5 form-inline">
                <input class="form-control input-sm" type="text" name="end_day" value=""/>
                <input class="form-control input-sm" type="text" name="end_time" value=""/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>件名:</label></div>
            <div class="col-xs-5">
                <input class="form-control input-sm" type="text" name="summary" value=""/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>本文:</label></div>
            <div class="col-xs-5">
                <textarea class="form-control" name="description"></textarea><br/>
            </div>
        </div>
        <div>
        <input type="submit" class="btn btn-default" />
        </div>
        </form>
    </div>
</div>
</body>
</html>

⑧:form.phpの見た目はこのようになります。

ws000104

⑨:データ書き込み処理は、functions.phpというファイルを用意して、ファイル内に関数を作成し処理をまとめたいと思います。

⑩:まずはjsonファイルからGoogleClientオブジェクトを取得する関数をfunctions.phpに作成します。

<?php
/**
 * jsonファイルからGoogleClientを生成します
 */
function getGoogleClientByJson() {
    $json_path = __DIR__.'/google-api-php-client/key/xxxxxxxxxxx.json'; // jsonファイルのパスをここに書いてください。
    $json_string = file_get_contents($json_path, true);

    $json = json_decode($json_string, true);

    $private_key = $json['private_key'];
    $client_email = $json['client_email'];

    $scopes = array(Google_Service_Calendar::CALENDAR);

    $credentials = new Google_Auth_AssertionCredentials(
        $client_email,
        $scopes,
        $private_key
    );

    $client = new Google_Client();
    $client->setApplicationName("Google Calendar PHP API");
    $client->setAssertionCredentials($credentials);
    if ($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion();
    }
    return $client;
}

⑪:次にformから渡ったデータをGoogleカレンダーに書き込む関数をfunctions.phpに作成します。
※上記のgetGoogleClientByJson関数の後に追記してください。

/**
 * カレンダーにデータを書き込む
 *
 * @param string $calendarId :カレンダーID
 * @param int    $allDay     :終日かどうか(1の場合は終日として登録)
 * @param string $startDay   :開始日
 * @param string $startTime  :開始時間($allDay=1のときは無視されます)
 * @param string $endDay     :終了日
 * @param string $endTime    :終了時間($allDay=1のときは無視されます)
 * @param string $summary    :カレンダーの件名に登録されます
 * @param string $description:カレンダーの説明に登録されます
 */
function writeGoogleCalendar($calendarId, $allDay, $startDay, $startTime, $endDay, $endTime, $summary, $description) {
    $client = getGoogleClientByJson();
    $service = new Google_Service_Calendar($client);
    $dt1 = new DateTime($startDay.' '.$startTime);
    $dt2 = new DateTime($endDay.' '.$endTime);

    if ($allDay == 1) {
        // $allDayが1であれば、終日で登録する
        $event = new Google_Service_Calendar_Event(array(
          'summary' => $summary,
          'description' => $description,
          'start' => array(
            'date' => $dt1->format('Y-m-d'), // 開始日
            'timeZone' => 'Asia/Tokyo',
          ),
          'end' => array(
            'date' => $dt2->format('Y-m-d'), // 終了日
            'timeZone' => 'Asia/Tokyo',
          ),
        ));
    } else {
        // $allDayが1以外であれば、日時で登録する
        $st = $dt1->getTimestamp();
        $et = $dt2->getTimestamp();
        $event = new Google_Service_Calendar_Event(array(
          'summary' => $summary,
          'description' => $description,
          'start' => array(
            'dateTime' => date('c', $st), // 開始日時
            'timeZone' => 'Asia/Tokyo',
          ),
          'end' => array(
            'dateTime' => date('c', $et), // 終了日時
            'timeZone' => 'Asia/Tokyo',
          ),
        ));
    }
    $event = $service->events->insert($calendarId, $event);
}

⑫:カレンダーに予定を書き込むプログラムは準備できましたので、form.phpにfunctions.phpを呼び出す処理をいれて、Googleカレンダーに登録できるようにします。さきほどのform.phpを以下のように修正します。
※注意:以下の処理は、POSTの値の正常判定を行っておらず脆弱性があります、本番公開しないように気をつけてください。

<?php
require_once __DIR__.'/google-api-php-client/src/Google/autoload.php';
require_once __DIR__.'/functions.php';
if (strtolower($_SERVER['REQUEST_METHOD'])=='post') {
    $calendarId    = 'ここに6.Googleカレンダーの準備」の⑥で取得したカレンダーIDを入れます';
    $allDay        = $_POST['all_day'];
    $startDay      = $_POST['start_day'];
    $startTime     = $_POST['start_time'];
    $endDay        = $_POST['end_day'];
    $endTime       = $_POST['end_time'];
    $summary       = $_POST['summary'];
    $description   = $_POST['description'];
    $event = writeGoogleCalendar($calendarId, $allDay, $startDay, $startTime, $endDay, $endTime, $summary, $description);
} else {
    $startDay  = date('Y-m-d');
    $startTime = '00:00:00';
    $endDay    = date('Y-m-d');
    $endTime   = '00:00:00';
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width">
<title>Googleカレンダー登録用フォーム</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"/>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
    <div class="col-xs-1">
    </div>
    <div class="col-xs-11">
        <h1>Googleカレンダー登録用フォーム</h1>
        <form method="post">
        <div class="row">
            <div class="col-xs-2"><label>終日:</label></div>
            <div class="col-xs-5 form-inline">
                <select class="form-control" name="all_day">
                    <option value="0">いいえ</option>
                    <option value="1">はい</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>開始時間:</label></div>
            <div class="col-xs-5 form-inline">
                <input class="form-control input-sm" type="text" name="start_day" value="<?=$startDay?>"/>
                <input class="form-control input-sm" type="text" name="start_time" value="<?=$startTime?>"/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>終了時間:</label></div>
            <div class="col-xs-5 form-inline">
                <input class="form-control input-sm" type="text" name="end_day" value="<?=$endDay?>"/>
                <input class="form-control input-sm" type="text" name="end_time" value="<?=$endTime?>"/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>件名:</label></div>
            <div class="col-xs-5">
                <input class="form-control input-sm" type="text" name="summary" value=""/>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2"><label>本文:</label></div>
            <div class="col-xs-5">
                <textarea class="form-control" name="description"></textarea><br/>
            </div>
        </div>
        <div>
        <input type="submit" class="btn btn-default" />
        </div>
        </form>
    </div>
</div>
</body>
</html>

 
⑬:ディレクトリ構成は以下の様になります。

googlecalendar/
┣ form.php
┣ functions.php
┗ google-api-php-client/
  ┣ key/
     xxxxx.json
  ┗ src/
         Google
       ・・・・・・

 
以上でプログラムの準備ができました。
 
 

8.作成したプログラムを動作させてみます。

1):終日なしで登録
①: http://www.example.com/googlecalendar/form.php をブラウザで開きます。
※www.example.comの部分はダミーのURLです、URLは各々の環境に合わせて変更してください。
 
②:以下の情報を入力して、「送信」ボタンを押します。
・終日:
=>「いいえ」
・開始時間:
=>2017-04-27 10:00:00
・終了時間:
=>2017-04-27 20:00:00
・件名:
=>テストの件名
・本文:
=>テスト本文1
  テスト本文2ws000124

③:「hoge」カレンダーにこの様な形で登録できました。ws000125

2):終日ありで登録
①:さきほどのフォームで以下の情報を入力して、「送信」ボタンを押します。
・終日:
=>「はい」
・開始時間:
=>2017-04-27 10:00:00
・終了時間:
=>2017-04-29 20:00:00
・件名:
=>テストの件名2
・本文:
=>テスト本文
  テスト本文ws000126

②:「hoge」カレンダーにこの様な形で登録できました。
4月29日の20:00までと指定しましたが、終日ありで登録すると時間は無視されるので、4月27日~4月28日で登録されました。ws000127

以上で、PHPを使ってGoogleカレンダーの予定をフォームで入力して登録することができました。

このままのプログラムではPOSTの値の値判定を行っておらず脆弱性がありますが、
Googleカレンダーに予定を書き込むプログラムを作成したいときはこちらを参考にしていただければと思います。