IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  XML | 오픈 소스 | 웹 개발  >

PHP 프로그램에서 구글 캘린더 사용하기

PHP 응용 프로그램에서 구글 캘린더 정보를 가져와 통합하자

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Vikram Vaswani, 창립자, Melonfire

옮긴이: 박재호 이해영 dwkorea@kr.ibm.com

2008 년 9 월 09 일

구글 캘린더는 웹 응용 프로그램 개발자에게 사용자가 입력한 내용과 이벤트 정보를 REST 기반 개발자 API로 가져오는 방법을 제공합니다. PHP의 SimpleXML 확장 기능과 젠드(Zend) 프레임워크의 GData 라이브러리는 구글 캘린더 API가 생성한 XML 피드를 처리해 PHP 응용 프로그램을 만들기에 이상적인 기술입니다. 이 기사에서는 1) 구글 캘린더 데이터 API를 소개하고, 2) 사용자가 만든 캘린더를 살펴보고, 3) 캘린더 이벤트를 추가/갱신하고, 4) 키워드로 캘린더를 검색해 봅니다.

소개

오랫 동안 내가 정기적으로 사용한 유일한 일정 관리 도구는 팜파일럿에 딸려나온 일정 관리 소프트웨어였다. 하지만 지난 몇 년에 걸쳐 나는 점차 구글 캘린더 애용자가 되었다. 웹-웨어(Web-ware)라는 사실 외에도 이벤트 소식을 공유하고, 초청장과 응답을 관리하고, 다양한 이벤트 유형을 처리하기가 편리한 덕분이다.

자주 쓰이는 약어 소개
  • API: Application Programming Interface
  • HTTP: Hypertext Transfer Protocol
  • PHP: PHP: Hypertext Preprocessor
  • REST: Representational state transfer
  • RSS: Really Simple Syndication
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

개발자 입장에서도 구글 캘린더는 흥미를 자극한다. 구글 캘린더 데이터 API를 사용하면 공개 캘린더나 개인 캘린더에 있는 정보를 바탕으로 새로운 응용 프로그램을 제작하기가 아주 쉽다. 구글 캘린더 API는 REST 모델을 따르며, XML을 인식하는 개발 도구라면 어디서나 사용할 수 있다. 게다가 이미 많은 프로그래밍 언어에서 (내가 가장 좋아하는 PHP에서도) 클라이언트 라이브러리를 제공한다.

이 기사에서는 구글 캘린더 데이터 API를 소개하고, PHP 프로그램에서 캘린더 정보를 통합하고 사용하는 방법을 살펴본다. 구체적으로는 다음과 같은 내용을 다룬다.

  • 사용자 공개 노트북에서 이벤트를 가져오는 방법
  • 새 이벤트를 추가하는 방법
  • 기존 이벤트를 수정하고 삭제하는 방법
  • 키워드나 날짜 범위로 이벤트를 검색하는 방법

자, 이제 시작해 보자!!




위로


구글 캘린더 데이터 API 이해하기

PHP 코드로 뛰어들기 전에 구글 캘린더 데이터 API부터 이해하자. 여느 REST 기반 서비스와 마찬가지로, 구글 캘린더 데이터 API 역시 (XML 형식으로 인수가 지정된) HTTP 요청을 받아 XML 형식으로 만들어진 응답을 반환한다. 클라이언트에서는 이 XML 응답을 분석한다. 구글 캘린더 데이터 API는 항상 요청한 정보를 포함한 Atom 피드나 RSS 피드로 응답을 보낸다.

구글 캘린더 API가 반환하는 피드는 흔히 (일반적인 응용 프로그램 입장에서 필요 이상으로) 상당히 많은 정보를 포함한다. 예를 들어, 구글 캘린더 계정으로 로그인한 후 캘린더 설정에서 비공개 주소를 찾는다. 이 주소는 다른 사람과 공유해서는 안 되며, 권한을 먼저 요청하지 않은 상태에서는 캘린더 피드에 읽기 전용 접근만 허용하며, http://www.google.com/calendar/feeds/userid/private-magicCookie/basic 형태다. 브라우저 주소란에 자신의 비공개 주소를 입력해보자(아니면 HTTP 클라이언트를 통해 피드를 GET 요청으로 보낸다). 그러면 Listing 1과 같은 피드가 표시된다.


Listing 1: 구글 캘린더 피드 예
                
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
 xmlns:batch='http://schemas.google.com/gdata/batch' 
 xmlns:gCal='http://schemas.google.com/gCal/2005' 
 xmlns:gd='http://schemas.google.com/g/2005'>
  <id>http://www.google.com/calendar/feeds/user@gmail.com/
   private-cookie/basic</id>
  <updated>2008-06-13T19:15:18.000Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind' 
  term='http://schemas.google.com/g/2005#event'/>
  <title type='text'>Joe User</title>
  <subtitle type='text'>Joe User</subtitle>
  <link rel='alternate' type='text/html' 
  href='http://www.google.com/calendar/embed?src=user@gmail.com'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://www.google.com/calendar/feeds/user@gmail.com/private-cookie/basic'/>
  <link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml' 
   href='http://www.google.com/calendar/feeds/user@gmail.com/private-cookie/basic/batch'
    />
  <link rel='self' type='application/atom+xml' 
  href='http://www.google.com/calendar/feeds/user@gmail.com/private-cookie/basic?
  max-results=25'/>
  <author>
    <name>Joe User</name>
    <email>user@gmail.com</email>
  </author>
  <generator version='1.0' uri='http://www.google.com/calendar'
  >Google Calendar</generator>
  <openSearch:totalResults>4</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <gCal:timezone value='Asia/Calcutta'/>
  <entry>
    <id>http://www.google.com/calendar/feeds/user@gmail.com/
    private-cookie/basic/xxxxxxxx</id>
    <published>2008-06-12T08:49:38.000Z</published>
    <updated>2008-06-13T19:06:21.000Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' 
    term='http://schemas.google.com/g/2005#event'/>
    <title type='html'>Swim party</title>
    <summary type='html'>When: Sat Jun 21, 2008 12pm to 3:30pm&nbsp;
IST<br>
<br>Event Status: confirmed</summary>
    <content type='html'>When: Sat Jun 21, 2008 12pm to 3:30pm 
IST<br />
<br />Event Status: confirmed</content>
    <link rel='alternate' type='text/html' 
    href='http://www.google.com/calendar/event?eid=cGxwbHExOYHHDlOHQ4ZjA
    yMGMgdmlrcmFtLm1lbG9uZmlyZUBnb29nxmNvbQ' title='alternate'/>
    <link rel='self' type='application/atom+xml' 
    href='http://www.google.com/calendar/feeds/user@gmail.com/
    private-cookie/basic/ddddddddddddddd/>
    <author>
      <name>Joe User</name>
      <email>user@gmail.com</email>
    </author>
  </entry>
  <entry>
    <id>http://www.google.com/calendar/feeds/user@gmail.com/
    private-cookie/basic/yyyyyyyyyyyyyyyy</id>
    <published>2008-06-12T08:48:30.000Z</published>
    <updated>2008-06-12T08:48:46.000Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' 
    term='http://schemas.google.com/g/2005#event'/>
    <title type='html'>Dinner with the gang</title>
    <summary type='html'>When: Wed Jun 11, 2008 7pm to 9:30pm&nbsp;
IST<br>
<br>Event Status: confirmed</summary>
    <content type='html'>When: Wed Jun 11, 2008 7pm to 9:30pm 
IST<br />
<br />Event Status: confirmed</content>
    <link rel='alternate' type='text/html' 
    href='http://www.google.com/calendar/event?eid=
    MmhpYmV2cmowMM2kam9lZDQgdcmFtLm1lbG9uZmlyZU4858Bnb29nbGVtYWlsLmNvbQ' 
    title='alternate'/>
    <link rel='self' type='application/atom+xml' 
    href='http://www.google.com/calendar/feeds/user@gmail.com/private-cookie/
    basic/hhhhhhhhhhhhhhhhh'/>
    <author>
      <name>Joe User</name>
      <email>user@gmail.com</email>
    </author>
  </entry>
  <entry>
  ...
  </entry>
</feed>
        

모든 캘린더 피드는 <feed> 엘리먼트가 루트다. <feed> 엘리먼트는 여러 <link> 엘리먼트와 여러 <openSearch:> 엘리먼트를 포함한다. <link> 엘리먼트는 피드의 다른 버전 URL을 포함하며, <openSearch:> 엘리먼트는 요약 통계를 포함한다.

가장 바깥에 있는 <feed> 엘리먼트는 <entry> 엘리먼트를 한 개 이상 포함하며, 각 <entry> 엘리먼트는 좀 더 세부적인 캘린더 이벤트 정보를 포함한다. 이벤트 정보로는 제목, 설명, 작성일, 최종 수정일, 이벤트 피드 URL, 이벤트 작성자가 있다. 각각은 <title>, <summary>, <published>, <updated>, <link>, <author> 엘리먼트에 들어 있다.




위로


SimpleXML로 이벤트 목록 가져오기

다음은 PHP를 사용하여 구글 캘린더 피드를 처리하는 예제다. Listing 2는 Listing 1 피드를 받아 SimpleXML로 필요한 정보를 추출한 후 형식에 맞춰 웹 페이지에 표시한다.


Listing 2: SimpleXML로 이벤트 목록 가져오기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    $userid = 'username%40googlemail.com';
    $magicCookie = 'cookie';
    
    // 피드 URL 생성
    $feedURL = "http://www.google.com/calendar/feeds/$userid/private-$magicCookie/basic";
    
    // 피드를 SimpleXML 객체로 읽음
    $sxml = simplexml_load_file($feedURL);
    
    // 이벤트 개수 얻기
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> event(s) found.
    <p/>
    <ol>
    <?php    
    // 범주에 속한 항목 순회
    // 각 항목 세부 내역 출력
    foreach ($sxml->entry as $entry) {
      $title = stripslashes($entry->title);
      $summary = stripslashes($entry->summary);
      
      echo "<li>\n";
      echo "<h2>$title</h2>\n";
      echo "$summary <br/>\n";
      echo "</li>\n";
    }
    ?>
    </ol>
  </body>
</html>     
        

그림 1은 Listing 2로 얻은 결과다.


그림 1. SimpleXML로 가져온 캘린더 이벤트 목록
SimpleXML로 가져온 캘린더 이벤트 목록

Listing 2 코드를 살펴보면, simplexml_load_file() 함수는 피드 URL로 요청을 보낸 후 결과를 SimpleXML 객체로 변환한다. 그런 다음, foreach() 루프를 돌면서 <entry>를 하나씩 찾은 후 그림 1과 같은 정보를 추출한다. <entry> 엘리먼트 아래 있는 노드는 SimpleXML 객체 속성으로 참조한다. 예를 들어, <title> 노드는 $entry->title로, <summary> 노드는 $entry->summary로 참조한다.

여기서 사용한 피드 URL은 사용자의 비공개 캘린더 피드를 참조한다. 사용자의 비공개 캘린더 피드는 사용자 전자편지 주소와 매직 쿠키(magic cookie)라는 문자열을 포함하는데, 인증 과정을 거치지 않고 캘린더 자료를 읽기 전용으로 가져오는 경우에 비공개 주소를 사용한다. 앞서 언급했듯이, 이 피드 URL을 얻으려면 사용자의 구글 캘린더 페이지로 로그인한 후 캘린더 설정에서 URL을 직접 복사해 PHP 스크립트에 추가해야 한다.




위로


젠드 GData 클라이언트 라이브러리로 이벤트 목록 가져오기

매직 쿠키가 확실히 사용하기 편하지만, 일반 PHP 프로그램에서는 다음 두 가지 측면에서 실용적이지 못하다.

  • 캘린더 정보에 읽기 전용 접근만 가능하다.
  • (읽기 외에) 다른 캘린더 작업에는 사용하지 못한다.

캘린더 데이터 API로 (이벤트 수정, 삭제, 추가, 검색 등) 다양한 작업을 수행하려면 사용자 인증이 필요하다. 구글이 인정하는 인증 방법은 AuthSub과 ClientLogin 두 가지다.

사용자 인증 단계를 일일이 구현하기란 매우 번거롭다. 아주 전형적인 인증 단계라도 온갖 시나리오를 처리하려면 상당한 코드가 필요하다. 다행스럽게도 젠드 GData 클라이언트 라이브러리를 사용하면 개발자가 세세한 부분까지 신경쓸 필요가 없다. 젠드 GData 클라이언트 라이브러리는 PHP 응용 프로그램과 구글 데이터 API를 통합하는 과정에서 필요한 세부 사항을 모두 처리한다(라이브러리를 내려받는 링크는 참고자료에서 소개한다). 이 라이브러리는 구글 데이터 API와 연결하는 편리한 객체 지향 인터페이스를 제공하며, 사용자 인증 등 일반적인 작업을 거의 대부분 처리한다. 그러므로 개발자는 구글 데이터 API와 통신하는 방법을 신경쓸 필요 없이 응용 프로그램 자체에 집중할 수 있다.

Listing 3은 젠드 GData 클라이언트 라이브러리를 사용하여 Listing 2와 똑같은 기능을 구현한 코드다.


Listing 3: 젠드 라이브러리로 이벤트 리스트 가져오기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    // load library
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Calendar');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    // 캘린더 서비스를 위해 인증된 HTTP 클라이언트 생성
    $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
    $user = "username@gmail.com";
    $pass = "pass";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
    $gcal = new Zend_Gdata_Calendar($client);
    
    // 이벤트 목록을 얻기 위해 질의 생성
    $query = $gcal->newEventQuery();
    $query->setUser('default');
    $query->setVisibility('private');
    $query->setProjection('basic');
    
    // 캘린더 피드 획득과 해석
    // 결과 출력
    try {
      $feed = $gcal->getCalendarEventFeed($query);
    } catch (Zend_Gdata_App_Exception $e) {
      echo "Error: " . $e->getResponse();
    }
    ?>
    <h1><?php echo $feed->title; ?></h1>
    <?php echo $feed->totalResults; ?> event(s) found.
    <p/>
    <ol>

    <?php        
    foreach ($feed as $event) {
      echo "<li>\n";
      echo "<h2>" . stripslashes($event->title) . "</h2>\n";
      echo stripslashes($event->summary) . " <br/>\n";
      echo "</li>\n";
    }
    echo "</ul>";
    ?>
    </ol>

  </body>
</html>     
        

Listing 3은 가장 먼저 젠드 클래스 라이브러리를 로드한다. 그런 다음, Zend_Http_Client 클래스 인스턴스를 초기화한다. 이 클래스에 필요한 사용자 인증 정보를 제공한 후 캘린더 서비스에 인증된 채널로 연결한다. 인증 채널로 캘린더 서비스에 연결한 후에는 getCalendarEventFeed() 메서드로 캘린더 피드를 가져온다. 이 메서드는 EventQuery 객체를 받는데, 이 객체에 사용자 이름, 피드 유형(public 또는 private), 정보 상세 수준(full 또는 basic) 등 필요한 매개변수를 지정한다. getCalendarEventFeed() 메서드는 XML 문서를 반환하며, PHP 객체로 변환하는 작업을 거친다. 마지막으로 변환된 PHP 객체 속성에서 필요한 정보를 추출하여 HTML 페이지에 표시한다.

그림 2는 Listing 3으로 얻은 결과다.


그림 2. 젠드 GData 클라이언트 라이브러리로 가져온 캘린더 이벤트 목록
젠드 GData 클라이언트 라이브러리로 가져온 캘린더 이벤트 목록



위로


새 이벤트 추가하기

지금까지 클라이언트 프로그램에서 이벤트 목록만 가져왔다. 그렇다면 새로운 이벤트는 어떻게 추가할까?

생각보다 어렵지 않다. 구글 캘린더 데이터 API를 사용하면 간단하다. 먼저, XML 형식으로 이벤트 <entry> 엘리먼트를 생성한 후 캘린더 피드에 POST 메서드로 전송하면 그만이다. Listing 4는 새 이벤트를 나타내는 XML 예제다.


Listing 4: 새 이벤트를 나타내는 예제 XML
                
        <atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
          <atom:title type="text">Dinner with the gang</atom:title>
          <gd:when xmlns:gd="http://schemas.google.com/g/2005" 
          startTime="2008-06-23T18:00:00+05:30" endTime="2008-06-23T20:00:00+05:30"/>
        </atom:entry>
        

젠드 라이브러리를 사용하면 더욱 간단하다. insertEvent() 메서드만 호출하면 그만이다. insertEvent() 메서드가 Listing 4와 같은 XML을 생성하여 캘린더 피드로 전송한다. Listing 5는 이벤트 관련 정보를 사용자에게 받아 캘린더에 해당 이벤트를 추가하는 코드다. 아래서는 젠드 라이브러리를 사용하여 XML을 생성한다.


Listing 5: 웹 폼을 통해 새 이벤트 추가하기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Adding calendar events</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <h1>Add Event</h1>
    <?php if (!isset($_POST['submit'])) { ?>
    <form method="post" action="
     <?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Event title: <br/>
      <input name="title" type="text" size="15" /><p/>
      Start date (dd/mm/yyyy): <br/>
      <input name="sdate_dd" type="text" size="2" />
      <input name="sdate_mm" type="text" size="2" />
      <input name="sdate_yy" type="text" size="4" /><p/>
      Start time (hh:mm): <br/>
      <input name="sdate_hh" type="text" size="2" /> 
      <input name="sdate_ii" type="text" size="2" /><br/>
      End  date (dd/mm/yyyy): <br/>
      <input name="edate_dd" type="text" size="2" />
      <input name="edate_mm" type="text" size="2" />
      <input name="edate_yy" type="text" size="4" /><p/>
      End  time (hh:mm): <br/>
      <input name="edate_hh" type="text" size="2" /> 
      <input name="edate_ii" type="text" size="2" /><br/>
      <input name="submit" type="submit" value="Save" />      
    </form>
    <?php
    } else {
      // 클래스 로드
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Gdata');
      Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
      Zend_Loader::loadClass('Zend_Gdata_Calendar');
      Zend_Loader::loadClass('Zend_Http_Client');
      
      // 서비스에 접속
      $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
      $user = "username@gmail.com";
      $pass = "pass";
      $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
      $gcal = new Zend_Gdata_Calendar($client);
      
      // 입력 유효성 검사
      if (empty($_POST['title'])) {
        die('ERROR: Missing title');
      } 
      
      if (!checkdate($_POST['sdate_mm'], $_POST['sdate_dd'], $_POST['sdate_yy'])) {
        die('ERROR: Invalid start date/time');        
      }
      
      if (!checkdate($_POST['edate_mm'], $_POST['edate_dd'], $_POST['edate_yy'])) {
        die('ERROR: Invalid end date/time');        
      }
      
      $title = htmlentities($_POST['title']);
      $start = date(DATE_ATOM, mktime($_POST['sdate_hh'], $_POST['sdate_ii'], 
       0, $_POST['sdate_mm'], $_POST['sdate_dd'], $_POST['sdate_yy']));
      $end = date(DATE_ATOM, mktime($_POST['edate_hh'], $_POST['edate_ii'], 
       0, $_POST['edate_mm'], $_POST['edate_dd'], $_POST['edate_yy']));

      // 이벤트 객체 생성
      // 서버에 저장
      try {
        $event = $gcal->newEventEntry();        
        $event->title = $gcal->newTitle($title);        
        $when = $gcal->newWhen();
        $when->startTime = $start;
        $when->endTime = $end;
        $event->when = array($when);        
        $gcal->insertEvent($event);   
      } catch (Zend_Gdata_App_Exception $e) {
        echo "Error: " . $e->getResponse();
      }
      echo 'Event successfully added!';      
    }
    ?>
  </body>
</html>    
        

Listing 5는 크게 두 부분으로 나뉜다. 하나는 웹 폼이고, 다른 하나는 사용자가 웹 폼에 입력한 정보를 처리하는 PHP 코드다. 그림 3은 웹 폼을 보여준다.


그림 3. 새 이벤트를 추가하는 웹 폼
새 이벤트를 추가하는 웹 폼

일단 사용자가 이벤트 정보를 이 폼에 입력한 후 폼을 제출하면 코드 나머지 절반이 실행된다. 가장 먼저, 스크립트는 HTTP 클라이언트를 초기화한다. 이 과정에서 HTTP 클라이언트는 구글 캘린더 데이터 API와 인증된 연결을 연다. 다음으로, 스크립트는 사용자가 웹 폼에 입력한 정보를 검증한다. 이벤트 시작 날짜와 종료 날짜를 확인한 후 모든 날짜를 RFC 3339 형식으로 변환한다.

이벤트 정보를 검증한 후에는 새로운 EventEntry 객체를 생성한다. 이 객체는 캘린더에 삽입할 새 이벤트를 나타내며, newTitle()newWhen() 메서드를 제공한다. 스크립트는 두 메서드를 사용하여 이벤트 제목과 시작 날짜와 종료 날짜를 설정한다. 객체 속성을 모두 설정한 후에는 insertEvent() 메서드를 호출하여 구글 서버에 해당 이벤트를 저장한다. 저장한 이벤트는 캘린더에 즉시 표시된다.

그림 4는 캘린더에 새 이벤트를 성공적으로 추가한 후 얻어지는 결과다.


그림 4. 새 이벤트를 추가한 결과
새 이벤트를 추가한 결과



위로


기존 이벤트 삭제하고 수정하기

이벤트를 삭제하기는 더욱 쉽다. 해당 이벤트 URL을 얻은 후 해당 URL에 DELETE 요청을 보내면 그만이다. 젠드 라이브러리에서는 getCalendarEventEntry() 메서드로 이벤트 객체를 얻은 후 객체의 delete() 메서드를 호출한다. 자세한 내용은 Listing 6을 참조한다.


Listing 6: 이벤트 삭제하기
                
<?php
// 클래스 로드
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');
Zend_Loader::loadClass('Zend_Http_Client');

// 서비스에 연결
$gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$user = "username@gmail.com";
$pass = "pass";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
$gcal = new Zend_Gdata_Calendar($client);    

// 이벤트 인출
// 이벤트 삭제
try {          
  $event = $gcal->getCalendarEventEntry('http://www.google.com/calendar/
   feeds/default/private/full/xxxxxxx');
  $event->delete();
} catch (Zend_Gdata_App_Exception $e) {
  echo "Error: " . $e->getResponse();
}        
echo 'Event successfully deleted!';  
?>
        

이벤트를 수정하는 방법도 비슷하다. 해당 이벤트 URL을 얻은 후 이 URL에 PUT 요청과 수정할 정보를 보내면 그만이다. 젠드 라이브러리에서는 이벤트 객체 속성에 새 값을 설정한 후 save() 메서드로 변경된 값을 이벤트 서버로 보낸다. 자세한 내용은 Listing 7을 참조한다.


Listing 7: 이벤트 수정하기
                
<?php
// 클래스 로드
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');
Zend_Loader::loadClass('Zend_Http_Client');

// 서비스에 연결
$gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$user = "username@gmail.com";
$pass = "pass";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
$gcal = new Zend_Gdata_Calendar($client);    

// 이벤트 인출
// 새로운 이벤트 속성 설정과 이벤트 갱신
try {
  $event = $gcal->getCalendarEventEntry('http://www.google.com/calendar/feeds/
   default/private/full/xxxxxxxxxxx');
  $event->title = $gcal->newTitle($title); 
  $when = $gcal->newWhen();
  $when->startTime = $start;
  $when->endTime = $end;
  $event->when = array($when);         
  $event->save();   
} catch (Zend_Gdata_App_Exception $e) {
  die("Error: " . $e->getResponse());
}
echo 'Event successfully modified!';    
?>
        




위로


캘린더 작업 통합하기

지금까지 익힌 지식을 바탕으로 좀 더 실용적인 프로그램을 구현해 보자. Listing 8Listing 3을 개선한 코드로, 각 이벤트에 편집과 삭제 링크를 추가한다. 각 링크는 edit.php와 delete.php 스크립트를 가리키며, (이벤트 목록에서 추출한) 이벤트 식별자를 각 스크립트에 GET 메서드로 넘긴다.


Listing 8: 이벤트 목록 가져오기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Calendar');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
    $user = "username@gmail.com";
    $pass = "pass";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
    $gcal = new Zend_Gdata_Calendar($client);
    
    $query = $gcal->newEventQuery();
    $query->setUser('default');
    $query->setVisibility('private');
    $query->setProjection('basic');

    try {
      $feed = $gcal->getCalendarEventFeed($query);
    } catch (Zend_Gdata_App_Exception $e) {
      echo "Error: " . $e->getResponse();
    }
    ?>
    <h1><?php echo $feed->title; ?></h1>
    <?php echo $feed->totalResults; ?> event(s) found.
    <p/>
    <ol>

    <?php        
    foreach ($feed as $event) {
      echo "<li>\n";
      echo "<h2>" . stripslashes($event->title) . "</h2>\n";
      echo stripslashes($event->summary) . " <br/>\n";
      $id = substr($event->id, strrpos($event->id, '/')+1);
      echo "<a href=\"edit.php?id=$id\">edit</a> | ";
      echo "<a href=\"delete.php?id=$id\">delete</a> <br/>\n";
      echo "</li>\n";
    }
    echo "</ul>";
    ?>
    </ol>
    <p/>
    <a href="add.php">Add a new event</a><p/>
  </body>
</html>  
        

그림 5Listing 8을 실행한 결과다.


그림 5. 이벤트 목록을 표시하는 웹 페이지
이벤트 목록을 표시하는 웹 페이지

Listing 9는 delete.php 스크립트 코드다. 이 스크립트는 GET 메서드로 이벤트 식별자를 받아 해당 이벤트를 삭제한다. 구체적인 설명은 Listing 6을 참조한다.


Listing 9: 이벤트 삭제하기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Deleting calendar events</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <h1>Delete Event</h1>
    <?php
    // 클래스 로드
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Calendar');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    // 서비스에 연결
    $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
    $user = "username@gmail.com";
    $pass = "pass";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
    $gcal = new Zend_Gdata_Calendar($client);
      
    // 이벤트 ID가 존재하면
    // 피드에서 이벤트 객체를 얻는다.
    // 이벤트 삭제
    if (isset($_GET['id'])) {
      try {          
          $event = $gcal->getCalendarEventEntry('http://www.google.com/calendar/
           feeds/default/private/full/' . $_GET['id']);
          $event->delete();
      } catch (Zend_Gdata_App_Exception $e) {
          echo "Error: " . $e->getResponse();
      }        
      echo 'Event successfully deleted!';  
    } else {
      echo 'No event ID available';  
    }
    ?>
  </body>
</html>
        

Listing 10은 edit.php 스크립트 코드다.


Listing 10: 이벤트 편집하기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Updating calendar events</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <h1>Edit Event</h1>
    <?php
    // 클래스 로드
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Calendar');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    // 서비스에 연결
    $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
    $user = "username@gmail.com";
    $pass = "pass";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
    $gcal = new Zend_Gdata_Calendar($client);
     
    // 이벤트 세부 내역 얻기
    if (!isset($_POST['submit'])) {
      if (isset($_GET['id'])) {
        try {          
          $event = $gcal->getCalendarEventEntry('http://www.google.com/calendar/
           feeds/default/private/full/' . $_GET['id']);
        } catch (Zend_Gdata_App_Exception $e) {
          echo "Error: " . $e->getResponse();
        }
      } else {
          die('ERROR: No event ID available!');  
      }  
      
      // 자료를 사람이 읽을 수 있는 형식으로 변환
      // 이 레코드로 웹 폼 생성
      $title = $event->title;
      $when = $event->getWhen();
      $startTime = strtotime($when[0]->getStartTime());
      $sdate_dd = date('d', $startTime);
      $sdate_mm = date('m', $startTime);
      $sdate_yy = date('Y', $startTime);
      $sdate_hh = date('H', $startTime);
      $sdate_ii = date('i', $startTime);
      $endTime = strtotime($when[0]->getEndTime());
      $edate_dd = date('d', $endTime);
      $edate_mm = date('m', $endTime);
      $edate_yy = date('Y', $endTime);
      $edate_hh = date('H', $endTime);
      $edate_ii = date('i', $endTime);      
    ?>
    <form method="post" 
     action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      <input type="hidden" name="id" value="<?php echo $_GET['id']; ?>">
      Event title: <br/>
      <input name="title" type="text" size="15" 
       value="<?php echo $title; ?>"/><p/>
      Start date (dd/mm/yyyy): <br/>
      <input name="sdate_dd" type="text" size="2" 
       value="<?php echo $sdate_dd; ?>" />
      <input name="sdate_mm" type="text" size="2" 
       value="<?php echo $sdate_mm; ?>"/>
      <input name="sdate_yy" type="text" size="4" 
       value="<?php echo $sdate_yy; ?>"/><p/>
      Start time (hh:mm): <br/>
      <input name="sdate_hh" type="text" size="2" 
       value="<?php echo $sdate_hh; ?>"/> 
      <input name="sdate_ii" type="text" size="2" 
       value="<?php echo $sdate_ii; ?>"/><br/>
      End  date (dd/mm/yyyy): <br/>
      <input name="edate_dd" type="text" size="2" 
       value="<?php echo $edate_dd; ?>" />
      <input name="edate_mm" type="text" size="2" 
       value="<?php echo $edate_mm; ?>" />
      <input name="edate_yy" type="text" size="4" 
       value="<?php echo $edate_yy; ?>" /><p/>
      End  time (hh:mm): <br/>
      <input name="edate_hh" type="text" size="2" 
       value="<?php echo $edate_hh; ?>"  /> 
      <input name="edate_ii" type="text" size="2" 
       value="<?php echo $edate_ii; ?>"  /><br/>
      <input name="submit" type="submit" value="Save" />      
    </form>    
    <?php              
    } else {
      // 폼을 제출했다면
      // 입력한 정보를 검증
      if (empty($_POST['id'])) {
        die('ERROR: Missing event ID');
      } 
      
      if (empty($_POST['title'])) {
        die('ERROR: Missing title');
      } 
      
      if (!checkdate($_POST['sdate_mm'], $_POST['sdate_dd'], $_POST['sdate_yy'])) {
        die('ERROR: Invalid start date/time');        
      }
      
      if (!checkdate($_POST['edate_mm'], $_POST['edate_dd'], $_POST['edate_yy'])) {
        die('ERROR: Invalid end date/time');        
      }     
      
      $title = htmlentities($_POST['title']);
      $start = date(DATE_ATOM, mktime($_POST['sdate_hh'], $_POST['sdate_ii'], 
       0, $_POST['sdate_mm'], $_POST['sdate_dd'], $_POST['sdate_yy']));
      $end = date(DATE_ATOM, mktime($_POST['edate_hh'], $_POST['edate_ii'], 
       0, $_POST['edate_mm'], $_POST['edate_dd'], $_POST['edate_yy']));
      
      // 존재하는 이벤트 레코드를 가져옴
      // 이벤트 속성 갱신
      // 변경 사항을 서버에 저장
      try {
        $event = $gcal->getCalendarEventEntry('http://www.google.com/calendar/
         feeds/default/private/full/' . $_POST['id']);
        $event->title = $gcal->newTitle($title); 
        $when = $gcal->newWhen();
        $when->startTime = $start;
        $when->endTime = $end;
        $event->when = array($when);        
        $event->save();   
      } catch (Zend_Gdata_App_Exception $e) {
        die("Error: " . $e->getResponse());
      }
      echo 'Event successfully modified!';    
    }    
    ?>
  </body>
</html>  
        

Listing 9와 마찬가지로, Listing 10도 GET 메서드로 이벤트 식별자를 받는다. 그런 다음, getCalendarEventEntry() 메서드에 이벤트 식별자를 넘겨 해당 이벤트 정보를 가져온 후 세부 내역을 웹 폼으로 표시한다. 사용자는 폼에서 이벤트 정보를 살펴본 후 수정한다. 사용자가 수정한 폼을 제출하면 스크립트는 다시 구글 캘린더 데이터 API에 연결하고, 새 이벤트 정보가 담긴 <entry> 엘리먼트를 생성한 후, save() 메서드를 호출해 서버에 저장한다.




위로


이벤트 검색하기

여느 구글 데이터 API와 마찬가지로, 캘린더 API 역시 REST 질의에 다음과 같은 몇 가지 매개변수를 지정하는 방법으로 개발자가 결과를 제어할 수 있다.

  • 매개변수 start-index: 항목에서 시작 색인을 지정한다.
  • 매개변수 max-results: 가져올 항목 수를 지정한다.
  • 매개변수 start-min과 start-max: 반환할 항목에 대한 날짜 범위를 지정한다.
  • 매개변수 orderby: 정렬 방법을 지정한다.

Listing 11Listing 2에서 가져왔던 이벤트 목록 전체 중 다음 주 이벤트만 시작 날짜 순서로 가져오는 코드다.


Listing 11: 날짜로 이벤트 검색하기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    // 환경 설정 매개변수 설정
    $userid = 'username%40googlemail.com';
    $magicCookie = 'cookie';
    $start = urlencode(date(DATE_ATOM, strtotime('today 00:00')));
    $end = urlencode(date(DATE_ATOM, strtotime('+7 days 23:59')));
    
    // 피드 URL 생성
    $feedURL = "http://www.google.com/calendar/feeds/$userid/private-
     $magicCookie/basic?start-min=$start&start-max=$end&orderby=starttime";
    
    // 피드를 SimpleXML 객체로 읽음
    $sxml = simplexml_load_file($feedURL);
    
    // 이벤트 개수 얻기
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> event(s) found.
    <p/>
    <ol>
    <?php    
    // 범주에 속한 항목 순회
    // 각 항목 세부 내역 출력
    foreach ($sxml->entry as $entry) {
      $title = stripslashes($entry->title);
      $summary = stripslashes($entry->summary);
      
      echo "<li>\n";
      echo "<h2>$title</h2>\n";
      echo "$summary <br/>\n";
      echo "</li>\n";
    }
    ?>
    </ol>
  </body>
</html>    
        

또한 특정 질의 용어에 해당하는 항목만 반환하는 대신 전문 검색으로 캘린더를 검색한 후 해당 이벤트만 반환하는 방법도 있다. 구체적인 방법은 Listing 12를 참조한다.


Listing 12: 질의 용어로 이벤트 검색하기
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    // 환경 설정 매개변수 설정
    $userid = 'username%40googlemail.com';
    $magicCookie = 'cookie';
    $query = urlencode('party');
    
    // 피드 URL 생성
    $feedURL = "http://www.google.com/calendar/feeds/$userid/private-
     $magicCookie/basic?q=$query";
    
    // 피드를 SimpleXML 객체로 읽음
    $sxml = simplexml_load_file($feedURL);
    
    // 이벤트 개수 얻기
    $counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
    $total = $counts->totalResults; 
    ?>
    <h1><?php echo $sxml->title; ?></h1>
    <?php echo $total; ?> event(s) found.
    <p/>
    <ol>
    <?php    
    // 범주에 속한 항목 순회
    // 각 항목 세부 내역 출력
    foreach ($sxml->entry as $entry) {
      $title = stripslashes($entry->title);
      $summary = stripslashes($entry->summary);
      
      echo "<li>\n";
      echo "<h2>$title</h2>\n";
      echo "$summary <br/>\n";
      echo "</li>\n";
    }
    ?>
    </ol>
  </body>
</html>     
        

젠드 클라이언트 라이브러리도 이런 매개변수를 지원한다. Listing 13Listing 8 코드에 검색 폼과 폼 처리기를 추가한 코드다.


Listing 13: 사용자와 대화식 검색 기능 추가
                
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Listing calendar contents</title>
    <style>
    body {
      font-family: Verdana;      
    }
    li {
      border-bottom: solid black 1px;      
      margin: 10px; 
      padding: 2px; 
      width: auto;
      padding-bottom: 20px;
    }
    h2 {
      color: red; 
      text-decoration: none;  
    }
    span.attr {
      font-weight: bolder;  
    }
    </style>    
  </head>
  <body>
    <?php
    require_once 'Zend/Loader.php';
    Zend_Loader::loadClass('Zend_Gdata');
    Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
    Zend_Loader::loadClass('Zend_Gdata_Calendar');
    Zend_Loader::loadClass('Zend_Http_Client');
    
    $gcal = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
    $user = "username@gmail.com";
    $pass = "pass";
    $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $gcal);
    $gcal = new Zend_Gdata_Calendar($client);
    
    $query = $gcal->newEventQuery();
    $query->setUser('default');
    $query->setVisibility('private');
    $query->setProjection('basic');
    $query->setOrderby('starttime');
    if(isset($_GET['q'])) {
      $query->setQuery($_GET['q']);      
    }
    
    try {
      $feed = $gcal->getCalendarEventFeed($query);
    } catch (Zend_Gdata_App_Exception $e) {
      echo "Error: " . $e->getResponse();
    }
    ?>
    <h1><?php echo $feed->title; ?></h1>
    <?php echo $feed->totalResults; ?> event(s) found.
    <p/>
    <ol>

    <?php        
    foreach ($feed as $event) {
      echo "<li>\n";
      echo "<h2>" . stripslashes($event->title) . "</h2>\n";
      echo stripslashes($event->summary) . " <br/>\n";
      $id = substr($event->id, strrpos($event->id, '/')+1);
      echo "<a href=\"edit.php?id=$id\">edit</a> | ";
      echo "<a href=\"delete.php?id=$id\">delete</a> <br/>\n";
      echo "</li>\n";
    }
    echo "</ul>";
    ?>
    </ol>
    <p/>
    <a href="add.php">Add a new event</a><p/>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
      Search for events containing:<br/>
      <input type="text" name="q" size="10"/><p/>
      <input type="submit" name="submit" value="Search"/>
    </form>
  </body>
</html>    
        

Listing 13을 실행한 결과는 그림 6과 같다.


그림 6. 검색 폼
검색 폼

그림 7은 'party'라는 낱말이 포함된 모든 이벤트를 검색한 결과다.


그림 7. 캘린더 검색 결과
캘린더 검색 결과



위로


요약

이상이다. 지금까지 PHP 프로그램에 구글 캘린더 서비스를 통합하는 방법을 살펴봤다. 구체적으로는 SimpleXML과 젠드 클라이언트 라이브러리를 사용하는 방법을 익혔다. 이 기사에서는 살펴본 내용은 다음과 같다.

  • 구글 캘린더 피드 형식 소개
  • 날짜와 키워드로 캘린더를 검색하는 방법
  • 캘린더 이벤트를 추가하고 수정하고 삭제하는 방법
  • 구글 캘린더를 바탕으로 나름대로 서비스를 구현하는 방법

위 예제에서 보듯이, 구글 캘린더 데이터 API는 완성도가 높고, 사용하기 편하며, 유연성도 높다. 그래서 개발자 입장에서 구글 캘린더를 바탕으로 자신만의 웹 앞단을 생성하기가 매우 쉽다. 직접 사용하면서 가능성을 짚어보기 바란다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
이 글의 예제 코드x-googleclndr-code.ziptKBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기
  • SimpleXML 확장: XML을 PHP 객체로 바꿔주는 도구다. 객체는 속성 선택기(property selector)와 배열 반복자(array iterator)를 제공하므로 PHP 프로그램에서 XML 엘리먼트를 쉽게 참조할 수 있다.

  • The Zend GData Client Library: PHP에서 구글 데이터 API를 사용하려면 젠드 사에서 제공하는 PHP 5 GData 클라이언트 인터페이스가 필요하다.

  • 제품 평가를 위한 IBM 실험판 소프트웨어: developerWorks에서 직접 내려 받아 다음 프로젝트에 활용해보자. DB2®, Lotus®, Rational®, Tivoli®, WebSphere®와 같은 미들웨어와 용응 프로그램이 있다.


토론


필자소개

Vikram Vaswani는 Melonfire 사의 창립자이자 CEO다. Melonefire 사는 오픈 소스 도구와 기술을 전문으로 다루는 컨설팅 서비스 회사다. Vikram Vaswani는 PHP Programming SolutionsHow to do Everything with PHP and MySQL을 저술한 지은이이기도 하다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States, and/or other countries. IBM, the IBM logo, ibm.com, DB2, developerWorks, Lotus, Rational, Tivoli, WebSphere, and pureXML are trademarks of IBM Corporation in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의