如何使用 PHP 创建 Google 日历的列表视图
How to create a list view of Google Calendar with PHP
我需要将 Google 日历中的事件列表放在网页上。
我需要的列表可以在 Google 日历本身中看到,它是事件列表(议程样式),内容来自多个不同颜色的日历。
Google 日历也允许在 iframe 中包含此列表,但问题是,要查看这些列表,用户必须登录,否则我需要制作日历 public,但我做不到做。
以前有私人日历 url,但现在只有 iCal 提要私人可用。
所以我试图找到一个 PHP 脚本来创建这样一个列表。
令人惊讶的是,我没有找到太多。
大多数页面依赖于 public 日历,或者只是关于如何连接的非常基本的示例,例如 Google 的 php 示例
https://developers.google.com/google-apps/calendar/quickstart/php#step_3_set_up_the_sample
我设法开始工作,但这与我需要的相去甚远。
我需要一些可以格式化的 html 输出,以及来自 3 个不同日历的数据。
要做到这一点让我有点头疼,但也许有人以前做过类似的事情,在其他地方见过吗?
或者能够摆脱他们的袖子?
或者有更好的建议?
我做的另一个尝试是使用 phantomjs 登录日历并截屏,但我不能 运行 在我的网络服务器上。
我设法用下面的代码模仿了议程视图。
我遇到了一些问题,即全天活动的结束日期是第二天,非全天活动返回日期时间与全天的唯一日期。
我认为代码过于复杂,这是我在缓慢的迭代步骤中找到解决方案...
<html>
<head>
<style type="text/css">
html {
font-family: sans-serif;
}
.trips {
color:red;
}
.courses {
color:blue;
}
.canceled {
color:orange;
text-decoration:line-through;
}
.marketing {
color:green;
}
tr>td {
vertical-align: top;
}
td.time {
width: 110px;
}
td.date {
width: 140px;
}
td.summary {
font-weight:bold;
}
td {
padding: 0 0 5px 0;
border-bottom: 2px solid grey;
}
td td {
border-bottom: none;
}
span.location {
font-weight:normal;
color:black;
margin-left:10px;
}
</style>
</head>
<body>
[html comment broken up, to keep syntax highlighting in the php below]
< ! -- // having a html comment around php keeps php debug output from echo, print_r etc in source view
<?php
/******************
* list calendar-events mimicking the google calendar agenda-view
* allows to show a non-public calendars to non-authenticated clients
* code fragments from
* http://www.daimto.com/google-calendar-api-with-php-service-account/
* https://developers.google.com/google-apps/calendar/v3/reference/events/list#response
* https://developers.google.com/google-apps/calendar/quickstart/php#step_3_set_up_the_sample
******************/
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$Email_address = 'k....e@b....3.iam.gserviceaccount.com';
// for security reasons, keep key_file outside webroot:
$key_file_location = '/home/t...../...41.p12';
$client = new Google_Client();
$client-> setApplicationName("K....");
$key = file_get_contents($key_file_location);
// the calendars to query
$calendars = array(
'trips' => 'k....st@group.calendar.google.com',
'courses' => '3....4s@group.calendar.google.com',
'canceled' => 'p....f@group.calendar.google.com',
);
$agenda = array(); // the merged result from all calendarsi
$maxResults = 15; // no. of results to get (per calendar)
$firstDate = new DateTime(); // the date from which on we want the agenda
$firstDate->setTime(0,0,0); // date "without" time, we think in full days only
// $firstDate->modify('+2 days'); // testing other start-dates
setlocale (LC_ALL, 'de_DE'); // to get weekdays & monthnames correct
$scopes ="https://www.googleapis.com/auth/calendar.readonly";
$cred = new Google_Auth_AssertionCredentials(
$Email_address,
array($scopes),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service = new Google_Service_Calendar($client);
foreach($calendars as $cal_name => $cal_id) {
// get the dates from each calendar
$calendar_res = $service->calendars->get($cal_id);
$optParams = array(
'maxResults' => $maxResults,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => $firstDate->format('c')
);
$events = $service->events->listEvents($calendar_res->id, $optParams);
foreach ($events->getItems() as $event) {
$startDate = new DateTime();
$endDate = new DateTime();
// full-day events use 'date', others 'dateTime' so we need to treat separately:
if(isset($event->start->date)){
// it's a full day event, only a date is given
$startDate->setTimestamp(strtotime($event->start->date));
$endDate->setTimestamp(strtotime($event->end->date));
// full-day end-date is returned by google as the next day (midnight),
// correct this for our display:
$endDate->sub(new DateInterval('P1D'));
// remove times, they would contain data from the last processed non- full-day event
// also, we will test ifset to recognize full- against non- full-day events
unset($startTime);
unset($endTime);
}else{
// it's a non-full day, having start/end dates AND times
$startDate->setTimestamp(strtotime($event->start->dateTime));
$endDate->setTimestamp(strtotime($event->end->dateTime));
// extract times
$startTime = $startDate->format('G:i');
$endTime = $endDate->format('G:i');
// set times to zero, so date comparison works correctly
$startDate->setTime(0,0,0);
$endDate->setTime(0,0,0);
}
// for every day of the event, make an entry in the agenda
$currDate = $startDate; // the date we are about to add an entry to
while ($endDate >= $currDate){
// don't add entries that are before our first wanted date
if ($currDate >= $firstDate){
if (isset ($startTime)){
$time = $startTime . " - " . $endTime;
}else{
$time = "Ganztägig";
};
// we save the date in a way so the agenda-array can later be sorted by it
$agenda[$currDate->format('Y-m-d')][] =
array(
'cal' => $cal_name,
'summary' => $event->getSummary(),
'location' => $event->getLocation(),
'start' => $startDate->format('Y-m-d') . " - " . $startTime,
'end' => $endDate->format('Y-m-d') . " - " . $endTime,
'time' => $time
);
};
// go to next day
$currDate->modify('+1 day');
};
}
}
// the agenda-array is not yet sorted, events were added by calendar by date, not just by date
ksort ($agenda); // sort by key (date)
//var_dump($agenda);
//print_r($agenda);
?>
// end of html comment around php (keeps debug output in source view) -->
<?
//output
echo " <table>";
foreach ($agenda as $aDate => $events){
// a row for every date
echo "\n <tr>";
echo "\n <td class=\"date\">" . strftime('%a %e. %B', strtotime($aDate)) . "</td>";
echo "\n <td>";
// a table of events for every day
echo "\n <table >";
foreach ($events as $aEvent){
// a row for every event
echo "\n <tr>";
echo "\n <td class=\"time\">" . $aEvent['time'] ."</td>";
echo "\n <td class=\"" . $aEvent['cal'] . " summary\">" . $aEvent['summary'];
echo "\n <span class=\"location\">" . $aEvent['location'] . "</span>";
echo "\n </td>";
echo "\n </tr>";
};
echo "\n </table>";
echo "\n </td>";
echo "\n </tr>";
};
echo "\n <table>\n";
?>
</body>
</html>
这里有一些代码,如果 GET phone 号码位于 google 事件字段中的某处,有 5 种不同的 phone 数字格式之一,您将需要与日历共享的服务帐户以及创建服务帐户时获得的我的 Project.json 文件需要放入服务器上的工作文件夹(与 .
相同的文件夹)
<?php
//error_reporting(E_ALL);
//ini_set("display_errors", 1);
require_once __DIR__.'/vendor/autoload.php';
$client = new Google_Client();
$credentialJson= __DIR__ . '/My Project-somehexidecimal.json'; //name of your My Project .json file
$calendarId='youremail'; //your google calendar id
$phone= $_GET['phone'];
$display = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '--', $phone);
$display1 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '() -', $phone);
$display2 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '', $phone);
$display3 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', ' ', $phone);
$display4 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '()-', $phone);
$client->setAuthConfig($credentialJson);
$client->addScope('https://www.googleapis.com/auth/calendar');
$service = new Google_Service_Calendar($client);
$params = array(
'q' => $display,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params1 = array(
'q' => $display1,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params2 = array(
'q' => $display2,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params3 = array(
'q' => $display3,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params4 = array(
'q' => $display4,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$events = $service->events->listEvents($calendarId, $params);
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params1);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params2);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params3);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params4);
}
if (count($events->getItems()) == 0) {
print "No upcoming events found.\n";
}
$calTimeZone = $events->timeZone;
date_default_timezone_set($calTimeZone);
foreach ($events->getItems() as $event) {
$starttime= $event->getstart()['dateTime'];
$endtime= $event->getend()['dateTime'];
$description=$event->getDescription();
$summary=$event->getSummary();
$eventid = $event->getid();
$location = $event->getlocation();
$eventDateStr = $event->start->dateTime;
if(empty($eventDateStr))
{
$eventDateStr = $event->start->date;
}
$temp_timezone = $event->start->timeZone;
if (!empty($temp_timezone)) {
$timezone = new DateTimeZone($temp_timezone);
} else { $timezone = new DateTimeZone($calTimeZone);
}
$eventdate = new DateTime($eventDateStr,$timezone);
$link = $event->htmlLink;
$TZlink = $link . "&ctz=" . $calTimeZone;
$newmonth = $eventdate->format("M");
$newday = $eventdate->format("j");
}
?>
<div class="event-container">
<div class="eventDate">
<span class="month"><?php
echo $newmonth;
?></span><br />
<span class="day"><?php
echo $newday;
?></span><span class="dayTrail"></span>
</div>
<div class="eventBody">
<a href="<?php echo $TZlink;
?>">
<?php echo $summary, '<br>', $location, '<br>', $description;
?>
</a>
</div>
</div>
<?php
$notes= html_entity_decode ($description)
?>
我需要将 Google 日历中的事件列表放在网页上。 我需要的列表可以在 Google 日历本身中看到,它是事件列表(议程样式),内容来自多个不同颜色的日历。 Google 日历也允许在 iframe 中包含此列表,但问题是,要查看这些列表,用户必须登录,否则我需要制作日历 public,但我做不到做。
以前有私人日历 url,但现在只有 iCal 提要私人可用。
所以我试图找到一个 PHP 脚本来创建这样一个列表。 令人惊讶的是,我没有找到太多。 大多数页面依赖于 public 日历,或者只是关于如何连接的非常基本的示例,例如 Google 的 php 示例 https://developers.google.com/google-apps/calendar/quickstart/php#step_3_set_up_the_sample 我设法开始工作,但这与我需要的相去甚远。 我需要一些可以格式化的 html 输出,以及来自 3 个不同日历的数据。
要做到这一点让我有点头疼,但也许有人以前做过类似的事情,在其他地方见过吗? 或者能够摆脱他们的袖子? 或者有更好的建议?
我做的另一个尝试是使用 phantomjs 登录日历并截屏,但我不能 运行 在我的网络服务器上。
我设法用下面的代码模仿了议程视图。
我遇到了一些问题,即全天活动的结束日期是第二天,非全天活动返回日期时间与全天的唯一日期。
我认为代码过于复杂,这是我在缓慢的迭代步骤中找到解决方案...
<html>
<head>
<style type="text/css">
html {
font-family: sans-serif;
}
.trips {
color:red;
}
.courses {
color:blue;
}
.canceled {
color:orange;
text-decoration:line-through;
}
.marketing {
color:green;
}
tr>td {
vertical-align: top;
}
td.time {
width: 110px;
}
td.date {
width: 140px;
}
td.summary {
font-weight:bold;
}
td {
padding: 0 0 5px 0;
border-bottom: 2px solid grey;
}
td td {
border-bottom: none;
}
span.location {
font-weight:normal;
color:black;
margin-left:10px;
}
</style>
</head>
<body>
[html comment broken up, to keep syntax highlighting in the php below]
< ! -- // having a html comment around php keeps php debug output from echo, print_r etc in source view
<?php
/******************
* list calendar-events mimicking the google calendar agenda-view
* allows to show a non-public calendars to non-authenticated clients
* code fragments from
* http://www.daimto.com/google-calendar-api-with-php-service-account/
* https://developers.google.com/google-apps/calendar/v3/reference/events/list#response
* https://developers.google.com/google-apps/calendar/quickstart/php#step_3_set_up_the_sample
******************/
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$Email_address = 'k....e@b....3.iam.gserviceaccount.com';
// for security reasons, keep key_file outside webroot:
$key_file_location = '/home/t...../...41.p12';
$client = new Google_Client();
$client-> setApplicationName("K....");
$key = file_get_contents($key_file_location);
// the calendars to query
$calendars = array(
'trips' => 'k....st@group.calendar.google.com',
'courses' => '3....4s@group.calendar.google.com',
'canceled' => 'p....f@group.calendar.google.com',
);
$agenda = array(); // the merged result from all calendarsi
$maxResults = 15; // no. of results to get (per calendar)
$firstDate = new DateTime(); // the date from which on we want the agenda
$firstDate->setTime(0,0,0); // date "without" time, we think in full days only
// $firstDate->modify('+2 days'); // testing other start-dates
setlocale (LC_ALL, 'de_DE'); // to get weekdays & monthnames correct
$scopes ="https://www.googleapis.com/auth/calendar.readonly";
$cred = new Google_Auth_AssertionCredentials(
$Email_address,
array($scopes),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service = new Google_Service_Calendar($client);
foreach($calendars as $cal_name => $cal_id) {
// get the dates from each calendar
$calendar_res = $service->calendars->get($cal_id);
$optParams = array(
'maxResults' => $maxResults,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => $firstDate->format('c')
);
$events = $service->events->listEvents($calendar_res->id, $optParams);
foreach ($events->getItems() as $event) {
$startDate = new DateTime();
$endDate = new DateTime();
// full-day events use 'date', others 'dateTime' so we need to treat separately:
if(isset($event->start->date)){
// it's a full day event, only a date is given
$startDate->setTimestamp(strtotime($event->start->date));
$endDate->setTimestamp(strtotime($event->end->date));
// full-day end-date is returned by google as the next day (midnight),
// correct this for our display:
$endDate->sub(new DateInterval('P1D'));
// remove times, they would contain data from the last processed non- full-day event
// also, we will test ifset to recognize full- against non- full-day events
unset($startTime);
unset($endTime);
}else{
// it's a non-full day, having start/end dates AND times
$startDate->setTimestamp(strtotime($event->start->dateTime));
$endDate->setTimestamp(strtotime($event->end->dateTime));
// extract times
$startTime = $startDate->format('G:i');
$endTime = $endDate->format('G:i');
// set times to zero, so date comparison works correctly
$startDate->setTime(0,0,0);
$endDate->setTime(0,0,0);
}
// for every day of the event, make an entry in the agenda
$currDate = $startDate; // the date we are about to add an entry to
while ($endDate >= $currDate){
// don't add entries that are before our first wanted date
if ($currDate >= $firstDate){
if (isset ($startTime)){
$time = $startTime . " - " . $endTime;
}else{
$time = "Ganztägig";
};
// we save the date in a way so the agenda-array can later be sorted by it
$agenda[$currDate->format('Y-m-d')][] =
array(
'cal' => $cal_name,
'summary' => $event->getSummary(),
'location' => $event->getLocation(),
'start' => $startDate->format('Y-m-d') . " - " . $startTime,
'end' => $endDate->format('Y-m-d') . " - " . $endTime,
'time' => $time
);
};
// go to next day
$currDate->modify('+1 day');
};
}
}
// the agenda-array is not yet sorted, events were added by calendar by date, not just by date
ksort ($agenda); // sort by key (date)
//var_dump($agenda);
//print_r($agenda);
?>
// end of html comment around php (keeps debug output in source view) -->
<?
//output
echo " <table>";
foreach ($agenda as $aDate => $events){
// a row for every date
echo "\n <tr>";
echo "\n <td class=\"date\">" . strftime('%a %e. %B', strtotime($aDate)) . "</td>";
echo "\n <td>";
// a table of events for every day
echo "\n <table >";
foreach ($events as $aEvent){
// a row for every event
echo "\n <tr>";
echo "\n <td class=\"time\">" . $aEvent['time'] ."</td>";
echo "\n <td class=\"" . $aEvent['cal'] . " summary\">" . $aEvent['summary'];
echo "\n <span class=\"location\">" . $aEvent['location'] . "</span>";
echo "\n </td>";
echo "\n </tr>";
};
echo "\n </table>";
echo "\n </td>";
echo "\n </tr>";
};
echo "\n <table>\n";
?>
</body>
</html>
这里有一些代码,如果 GET phone 号码位于 google 事件字段中的某处,有 5 种不同的 phone 数字格式之一,您将需要与日历共享的服务帐户以及创建服务帐户时获得的我的 Project.json 文件需要放入服务器上的工作文件夹(与 .
相同的文件夹)<?php
//error_reporting(E_ALL);
//ini_set("display_errors", 1);
require_once __DIR__.'/vendor/autoload.php';
$client = new Google_Client();
$credentialJson= __DIR__ . '/My Project-somehexidecimal.json'; //name of your My Project .json file
$calendarId='youremail'; //your google calendar id
$phone= $_GET['phone'];
$display = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '--', $phone);
$display1 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '() -', $phone);
$display2 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '', $phone);
$display3 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', ' ', $phone);
$display4 = preg_replace('/^(\d{3})(\d{3})(\d{4})$/', '()-', $phone);
$client->setAuthConfig($credentialJson);
$client->addScope('https://www.googleapis.com/auth/calendar');
$service = new Google_Service_Calendar($client);
$params = array(
'q' => $display,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params1 = array(
'q' => $display1,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params2 = array(
'q' => $display2,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params3 = array(
'q' => $display3,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$params4 = array(
'q' => $display4,
'singleEvents' => true,
//'orderBy' => 'startTime',
'timeMin' => date(DateTime::ATOM),
'maxResults' => 1
);
$events = $service->events->listEvents($calendarId, $params);
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params1);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params2);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params3);
}
if (count($events->getItems()) == 0) {
$events = $service->events->listEvents($calendarId, $params4);
}
if (count($events->getItems()) == 0) {
print "No upcoming events found.\n";
}
$calTimeZone = $events->timeZone;
date_default_timezone_set($calTimeZone);
foreach ($events->getItems() as $event) {
$starttime= $event->getstart()['dateTime'];
$endtime= $event->getend()['dateTime'];
$description=$event->getDescription();
$summary=$event->getSummary();
$eventid = $event->getid();
$location = $event->getlocation();
$eventDateStr = $event->start->dateTime;
if(empty($eventDateStr))
{
$eventDateStr = $event->start->date;
}
$temp_timezone = $event->start->timeZone;
if (!empty($temp_timezone)) {
$timezone = new DateTimeZone($temp_timezone);
} else { $timezone = new DateTimeZone($calTimeZone);
}
$eventdate = new DateTime($eventDateStr,$timezone);
$link = $event->htmlLink;
$TZlink = $link . "&ctz=" . $calTimeZone;
$newmonth = $eventdate->format("M");
$newday = $eventdate->format("j");
}
?>
<div class="event-container">
<div class="eventDate">
<span class="month"><?php
echo $newmonth;
?></span><br />
<span class="day"><?php
echo $newday;
?></span><span class="dayTrail"></span>
</div>
<div class="eventBody">
<a href="<?php echo $TZlink;
?>">
<?php echo $summary, '<br>', $location, '<br>', $description;
?>
</a>
</div>
</div>
<?php
$notes= html_entity_decode ($description)
?>