Googleカレンダーからデータ取得

ギターのレッスンをしていてレッスン記録をつけている。
最初は EverNote を利用していたが、Google カレンダーの方が何かと便利なのである時期に乗り換えた。

今までは、レッスン場所を予定のタイトルにしてその場所で何時から何時までレッスンという具合に記載し、レッスン記録はその中の「説明」欄にまとめて書いていた。
見返す時に一覧で見られて便利なのだが、「誰が何時にレッスン」と言う予定が分からないのである。

生徒さんの名前でレッスン予定を書き込み、時間によってスケジュール確認ができ、レッスン記録は生徒さんの名前の予定内の「説明」欄に書く。

こうすると、「生徒さんのレッスン内容が一覧で見られない。」と思っていたので躊躇していたのだが、それが出来るようだったので実行してみた。

作成したいレポートは以下のふたつ。

  • ある期間の全生徒さんのレッスン記録閲覧。
  • 特定の生徒さんのレッスン記録閲覧。

今回は日付をまたぐデータは無視、と言うかエラーがでなけりゃよしとする事にしました。
(レッスンは通常30分、グループでも1時間30分なので・・・。)

以下のページなどを参考に何とか出来ました。
Googleカレンダー情報をPHPで取得してみる2
システムエンジニアの今井様、タメになる記事をありがとうございました。

サービスアカウントキーを取得する。

  1. GoogleDeveloperConsole に行く。
  2. 「プロジェクトを作成」をクリック。
    2017-0212-01.jpg
  3. 適当な名前でプロジェクトを作成。
    2017-0212-02.jpg
  4. 次の画面で「calendar」と入力すると、「CalendarAPI」が表示されるのでクリック。
    2017-0212-04.jpg
  5. この画面で「有効にする」をクリック。
    2017-0212-05.jpg
  6. 下の画面で、左メニューの「認証情報」をクリック。
    2017-0212-07.jpg
  7. プロジェクトへの認証情報の追加
    「認証情報を作成」から「サービスアカウントキー」をクリック。
    「サービスアカウント」は「App Engine default service account」を選択「JSON」にチェックをいれて「作成」ボタンをクリック。
    2017-0212-09.jpg
  8. jsonファイルがダウンロードされるので、保存する。
    「新しい秘密鍵」画面が表示されるので「閉じる」をクリックして終了。
    2017-0212-10.jpg

google-api-php-clientプログラムを入手する。

Googleカレンダーからデータを取得するため、「google-api-php-client」というライブラリを使う。
現段階 (2017年2月12日現在) は「2.1.2」が最新バージョンのようでしたが、仕様が変わっているようでいろいろ設定を変更しなければならないようだったので僕は「1.1.6」を使いました。

  1. 下の場所へ行く。
    Releases · google/google-api-php-client · GitHub
    releases という箇所をクリックする。
    2017-0212-11.jpg
  2. 1.1.6 の「Source code(zip)」をクリックしてファイルをダウンロード。
    2017-0212-12.jpg

Googleカレンダーの準備。

  1. 「マイカレンダー」から「新しいカレンダー作成」をクリック。
    2017-0212-13.jpg
  2. 「カレンダー名」に名前を入れる。(ここでは「テスト」にした。)
    「ユーザー」にはダウンロードした json ファイルの中に記載されている「client_email」の値を入れ、「ユーザを追加」を押す。
    「カレンダーを作成」をクリックして終了。
    2017-0212-14.jpg
    ダウンロードした json ファイルの中身。
    緑色で記載されている「client_email」を上の「ユーザー」に入力する。
    2017-0212-15.jpg
  3. テスト用にデータを入れてみる。
    2017-0212-16.jpg

PHPからGoogleカレンダーの情報を取得してみる。

  1. 「テスト」カレンダー右の▼をクリックして、「カレンダー設定」をクリック。
    2017-0212-17.jpg
  2. 「カレンダーのアドレス」にある、「カレンダーID」を PHP プログラム内で使用するので記録しておく。
    2017-0212-18.jpg

PHPプログラムからカレンダー情報を取得する。

プログラムの設置場所は以下の通り。

  • PHPプログラム
    root/gcal/lsn-note.php/
  • google-api-php-client
    root/gcal/gcal-api/
  • json
    root/gcal/gcal-json/lsn-note.json/

使用したサンプルカレンダーはこれ。
2017-0212-16.jpg

h2PHP プログラムその1 (特定期間の全生徒さんのレッスン記録閲覧) require_once(“html.php”);←の「html.php」は html ヘッダとフッタを書き出すためのファイル。

 <?php
//関連ファイル読み込み
require_once("html.php");
//デフォルトタイムゾーンを設定(PHP5.1.0 から設定しないとエラーになる)
date_default_timezone_set('Asia/Tokyo');

//変数を受け取る
$datafrom = $_POST['DataFrom'];//データ取り出し方法 特定日または特定期間
if ($datafrom == "oneday"){//特定日の場合
	$from = $_POST['LessonDay'];//データ取得開始日
	$DataNum = $_POST['DataNum'];//データ取得数
	$sm = substr($from,4,2);
	$sd = substr($from,6,2);
	$sy = substr($from,0,4);
	$em = $sm;//データ取得終了日(データ取得開始日と同じ値をセット)
	$ed = $sd;
	$ey = $sy;
} else {//特定期間の場合
	$from = $_POST['from'];//データ取得開始日
	$to = $_POST['to'];//データ取得終了日
	$DataNum = $_POST['DataNum'];//データ取得数
	$sm = substr($from,4,2);
	$sd = substr($from,6,2);
	$sy = substr($from,0,4);
	$em = substr($to,4,2);
	$ed = substr($to,6,2);
	$ey = substr($to,0,4);
}

//特定期間のレッスン記録を取り出す
require_once __DIR__.'/gcal-api/src/Google/autoload.php';
$json_path = __DIR__.'/gcal-json/lsn-note.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_READONLY);

$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();
}

$service = new Google_Service_Calendar($client);

// データ取得範囲
$t = mktime(0, 0, 0, $sm, $sd, $sy);
$t2 = mktime(23, 59, 59, $em, $ed, $ey);
$calendarId = '◆◆◆◆◆';//カレンダーID

//データを先頭から件取得
$optParams = array(
  'maxResults' => $DataNum,//データ取得数
  'orderBy' => 'startTime',
  'singleEvents' => TRUE,
  'timeMin' => date('c', $t),
  'timeMax' => date('c', $t2),
);

$results = $service->events->listEvents($calendarId, $optParams);

//html書き出し
echo head();//<html><head></head>~<body>

//データ取りだし
$weekday = array( "日", "月", "火", "水", "木", "金", "土" );//曜日記載用の配列
if (count($results->getItems()) == 0) {
  echo "指定した期間にはデータがありません。\n";
	echo "<p>データ取得期間:".date('Y年n月j日',$t)."(".$weekday[date('w',$t)].")~".date('Y年n月j日',$t2)."(".$weekday[date('w',$t2)].")まで</p>\n";//データ取得日付を書き出し
} else {
	echo "<h1>レッスン記録</h1>";
	echo "<p>データ取得期間:".date('Y年n月j日',$t)."(".$weekday[date('w',$t)].")~".date('Y年n月j日',$t2)."(".$weekday[date('w',$t2)].")まで</p>\n";//データ取得日付を書き出し
	$LsnDay = "";//レッスン日初期化
	foreach ($results->getItems() as $event) {
		$DayCheck = $event->start->dateTime;//レッスン日時をチェック
		if (empty($DayCheck)) {
			$DayCheck = $event->start->date;//レッスン日を記載するかどうかのチェック、チェックした日のレッスン時間が空の場合は日を代入
      $starttime = "00時00分";//時間の記載がない場合はその旨表示する(赤字表示など)
      $endtime = "24時00分";
      $AllDay = true;
		} else {
			$starttime = substr($DayCheck,11,2)."時".substr($DayCheck,14,2)."分";
      $endtime = $event->end->dateTime;//時間の記載がある場合は終了時刻を取得しておく
      $endtime = substr($endtime,11,2)."時".substr($endtime,14,2)."分";
      $AllDay = false;
		}
		//レッスン日が変わった場合は日付を表示する
		$DayCheck = mktime(0,0,0,substr($DayCheck,5,2),substr($DayCheck,8,2),substr($DayCheck,0,4));//チェックした年月日のUNIXタイムスタンプを取得
		if ($LsnDay != $DayCheck){//レッスン日が変わった場合はレッスン日書き出し
				$LsnDay = $DayCheck;
				echo "<h2>".date('Y年n月j日',$LsnDay)."(".$weekday[date('w',$LsnDay)].")</h2>\n";
		}

		//データ書き出し
		$mark = "◆";//生徒さんの前に付けるマーク
		$summary = $event->summary;//生徒さんの名前
		$description = $event->description;//レッスン記録
		if ($AllDay == true){//時間の記載がない場合
			echo "<p class='time'>".$mark."$summary"." <span class='allday'>$starttime - $endtime</span></p>\n";
		}
		else {
			echo "<p class='time'>".$mark."$summary"." $starttime - $endtime</p>\n";
		}
		echo "<p class='description'>".nl2br($description)."\n</p>\n";
	}
}

//html書き出し
echo foot();//</body></html>

?>

いつもの事ながらコメント多いなぁ・・・。

実行結果
2017-0212-19.jpg

PHP プログラムその2 (特定の生徒さんのレッスン記録閲覧)

 <?php
//関連ファイル読み込み
require_once("html.php");
//デフォルトタイムゾーンを設定(PHP5.1.0 から設定しないとエラーになる)
date_default_timezone_set('Asia/Tokyo');

//変数を受け取る
$Student = $_POST['StudentName'];//取得したい生徒さんの氏名
$from = $_POST['from'];//データ取得開始日
$to = $_POST['to'];//データ取得終了日
$DataNum = $_POST['DataNum'];//データ取得数
$sm = substr($from,4,2);
$sd = substr($from,6,2);
$sy = substr($from,0,4);
$em = substr($to,4,2);
$ed = substr($to,6,2);
$ey = substr($to,0,4);

//特定期間のある生徒さんのレッスン記録を取り出す
require_once __DIR__.'/gcal-api/src/Google/autoload.php';
$json_path = __DIR__.'/gcal-json/lsn-note.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_READONLY);

$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();
}

$service = new Google_Service_Calendar($client);

// データ取得範囲
$t = mktime(0, 0, 0, $sm, $sd, $sy);
$t2 = mktime(23, 59, 59, $em, $ed, $ey);
$calendarId = '◆◆◆◆◆';//カレンダーID

//データを先頭から取得
$optParams = array(
  'maxResults' => $DataNum,//データ取得数
  'orderBy' => 'startTime',
  'singleEvents' => TRUE,
  'timeMin' => date('c', $t),
  'timeMax' => date('c', $t2),
);

$results = $service->events->listEvents($calendarId, $optParams);

//html書き出し
echo head();//<html><head></head>~<body>

//データ取りだし
$weekday = array( "日", "月", "火", "水", "木", "金", "土" );//曜日記載用の配列
if (count($results->getItems()) == 0) {
  echo "<p>指定した期間に<span class='nodata'>".$Student."さん</span>のデータはもちろん、その他のデータもありません。</p>\n";
	echo "<p>データ取得期間:".date('Y年n月j日',$t)."(".$weekday[date('w',$t)].")~".date('Y年n月j日',$t2)."(".$weekday[date('w',$t2)].")まで</p>\n";//データ取得日付を書き出し
} else {
	echo "<h1>".$Student."さんのレッスン記録</h1>";
	echo "<h2>データ取得期間:".date('Y年n月j日',$t)."(".$weekday[date('w',$t)].")~".date('Y年n月j日',$t2)."(".$weekday[date('w',$t2)].")まで</h2>\n";//データ取得日付を書き出し
	$LsnDay = "";//レッスン日初期化
	$DataCnt = 0;//データ数初期化
	foreach ($results->getItems() as $event) {
		$summary = $event->summary;//生徒さんの名前をチェック
		if ($summary == $Student){
			$DataCnt = $DataCnt +1;
			$DayCheck = $event->start->dateTime;//レッスン日時をチェック
			if (empty($DayCheck)) {
				$DayCheck = $event->start->date;//レッスン日を記載するかどうかのチェック、チェックした日のレッスン時間が空の場合は日を代入
	      $starttime = "00時00分";//時間の記載がない場合はその旨表示する(赤字表示など)
	      $endtime = "24時00分";
	      $AllDay = true;
			} else {
				$starttime = substr($DayCheck,11,2)."時".substr($DayCheck,14,2)."分";
	      $endtime = $event->end->dateTime;//時間の記載がある場合は終了時刻を取得しておく
	      $endtime = substr($endtime,11,2)."時".substr($endtime,14,2)."分";
	      $AllDay = false;
			}
			//レッスン日が変わった場合は日付を表示する
			$DayCheck = mktime(0,0,0,substr($DayCheck,5,2),substr($DayCheck,8,2),substr($DayCheck,0,4));//チェックした年月日のUNIXタイムスタンプを取得
			if ($LsnDay != $DayCheck){//レッスン日が変わった場合はレッスン日書き出し
					$LsnDay = $DayCheck;
					echo "<h2>".date('Y年n月j日',$LsnDay)."(".$weekday[date('w',$LsnDay)].")</h2>\n";
			}
			//データ書き出し
			$mark = "◆";//生徒さんの前に付けるマーク
			$description = $event->description;//レッスン記録
			if ($AllDay == true){//時間の記載がない場合
				echo "<p class='time'>".$mark."<span class='allday'>$starttime - $endtime</span></p>\n";
			}
			else {
				echo "<p class='time'>".$mark."$starttime - $endtime</p>\n";
			}
			echo "<p class='description'>".nl2br($description)."\n</p>\n";
		}
	}
	if ($DataCnt == 0){
		echo "<p>対象期間に<span class='nodata'>".$Student."さん</span>のレッスン記録はありません。</p>\n";
	} else {
		echo "<p>対象期間のレッスン回数:".$DataCnt."回</p>\n";
	}
}

//html書き出し
echo foot();//</body></html>

?>

実行結果
2017-0212-20.jpg

はぁ、出来たっと。

あとは、ブラウザから「取得期間」、「生徒さんの名前」などをセットして取得できるようにするだけです。

これで、いろいろ楽になるぞっと!!

めでたしめでたし!!

 

コメント