Интеграция контента Blogger с PHP-приложениями с помощью API Blogger Data

Использование PHP для извлечения и добавления заметок в Blogger с помощью многофункционального API Blogger Data

Blogger ― это популярная бесплатная платформа, которая позволяет создавать блоги и публиковать заметки и новости с помощью интерфейса редактирования WYSIWYG. API Blogger Data, основанный на технологии REST, обеспечивает доступ к содержимому Blogger с помощью любого XML-совместимого инструментария программирования. Эта статья учит пользоваться API Blogger Data для вывода содержания блога, добавления или редактирования заметок и манипулирования комментариями к блогу с помощью компонента Zend_Gdata Zend Framework. Мы создадим простое приложение, которое демонстрирует всю мощь API Blogger.

Викрам Васвани (Vikram Vaswani), основатель компании, Melonfire

Викрам Васвани (Vikram Vaswani) – основатель и президент консалтинговой фирмы Melonfire, специализирующейся на технологиях и инструментах с открытым исходным кодом. Также является автором книг Решения по программированию на PHP and Как сделать все что угодно с помощью PHP и MySQL.



06.07.2012

Введение

Возможно, вы слышали о Blogger, бесплатной платформе, которая позволяет легко создавать собственные блоги и публиковать заметки на любую тему. Существующая с 1999 года, эта блог-платформа была одной из первых в Интернете. Ее приобрела компания Google и интегрировала в свой набор бесплатных услуг.

Популярные приложения для блогеров

Blogger ― популярная блог-платформа, но существуют и многие другие. Например, программное обеспечение IBM Connections включает в себя встроенные возможности для блогеров. В числе других популярных платформ можно назвать Wordpress, Drupal, Typepad и многие другие.

С помощью Blogger можно создавать и поддерживать свои собственные блоги, не имея специальных технических знаний. Blogger:

  • содержит набор готовых шаблонов и макетов;
  • поддерживает комментарии, управление доступом и мобильные устройства;
  • тесно интегрирован с другими службами (Twitter, Google AdSense и др.) для обмена контентом и организации денежных отношений;

Короче, Blogger обеспечивает все необходимое для публикации собственного блога без углубления в технические детали.

Часто используемые сокращения

  • API: Application Program Interface - интерфейс прикладного программирования
  • HTML: HyperText Markup Language - язык разметки гипертекста
  • HTTP: Hypertext Transfer Protocol
  • REST: Representational State Transfer - передача репрезентативного состояния
  • RSS: Really Simple Syndication
  • URL: пользовательский интерфейс
  • WYSISYG: What You See Is What You Get - что видишь, то и получаешь
  • XML: Extensible Markup Language - расширяемый язык разметки

Но Blogger интересен не только пользователям. Как и многие другие службы Google, Blogger содержит API для разработчиков, который позволяет получить доступ к внутреннему устройству службы и извлекать контент для создания собственных специальных приложений и гибридов. API Blogger Data соответствует модели REST и доступен с помощью любого инструментария разработки, поддерживающего XML. Существуют клиентские библиотеки для многих распространенных языков программирования, включая мой любимый: PHP.

В этой статье мы рассмотрим API Blogger Data и способы интеграции и использования содержимого Blogger с PHP-приложениями. На множестве примеров вы научитесь:

  • подключать и проверять подлинность API;
  • получать списки блогов и каналов;
  • добавлять, редактировать и удалять содержимое;
  • работать с комментариями к блогам.

Основные понятия

Прежде чем углубиться в PHP-код, приведем в этом разделе обзор API Data Blogger. Как и все службы, базирующиеся на REST, API принимает HTTP-запросы, содержащие один или несколько входных аргументов на языке XML, и возвращает XML-ответы, которые можно обрабатывать в любой клиентской программе, поддерживающей XML. Ответ API Blogger всегда представляет собой канал Atom или RSS, содержащий запрашиваемую информацию.

Blogger поддерживает открытые и частные каналы. Доступ к открытым каналам, таким как списки публикаций в блоге, можно получить без регистрации. Частные каналы требуют аутентификации. Например, для добавления или редактирования заметки в блоге или комментария требуется аутентификация в частном канале. В примерах к этой статье демонстрируются каналы обоих типов.

Чтобы получить максимальную отдачу от этой статьи, нужно иметь учетную запись в Blogger и, по крайней мере, один блог и одну заметку. Для этого войдите в Blogger (см. раздел Ресурсы), создайте новый блог и добавьте в него новую заметку для целей тестирования. Войдя, попробуйте получить доступ к URL http://www.blogger.com/feeds/default/blogs в Web-браузере. Вы увидите нечто похожее на листинг 1.

Листинг 1. Метаканал Blogger
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
  <id>tag:blogger.com,1999:user-12345USERIDHERE12345.blogs</id>
  <updated>2011-09-02T03:35:34.547Z</updated>
  <title type='text'>V Vaswani's Blogs</title>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345USERIDHERE12345/blogs'/>
  <link rel='self' type='application/atom+xml' 
    href='http://www.blogger.com/feeds/12345USERIDHERE12345/blogs'/>
  <link rel='alternate' type='text/html' 
    href='http://www.blogger.com/profile/12345USERIDHERE12345'/>
  <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
  </author>
  <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
  <openSearch:totalResults>1</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <entry>
    <id>tag:blogger.com,1999:user-12345USERIDHERE12345.blog
     -12345BLOGIDHERE12345</id>
    <published>2008-02-19T23:30:41.755-08:00</published>
    <updated>2011-09-01T04:01:19.669-07:00</updated>
    <title type='text'>V Vaswani's Blog</title>
    <summary type='html'></summary>
    <link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/
     12345USERIDHERE12345/blogs/12345BLOGIDHERE12345'/>
    <link rel='alternate' type='text/html' href='http://vvaswani.blogspot.com/'/>
    <link rel='http://schemas.google.com/g/2005#feed' 
     type='application/atom+xml' 
     href='http://vvaswani.blogspot.com/feeds/posts/default'/>
    <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
    <link rel='http://schemas.google.com/blogger/2008#template' 
     type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/template'/>
    <link rel='http://schemas.google.com/blogger/2008#settings' 
     type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/settings'/>
    <author>
      <name>V Vaswani</name>
      <email>noreply@blogger.com</email>
    </author>
    <gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' 
     name='IS_PUBLIC_BLOG' value='true'/>
    <gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' 
     name='PICASAWEB_ALBUM_ID' value='0'/>
  </entry>
</feed>

Метаканал, приведенный в в листинге 1, содержит список всех блогов, связанных с текущим зарегистрированным пользователем. Он начинается с элемента <feed> в качестве корневого элемента. Элемент <feed> содержит:

  • элементы <link> с URL-адресами различных версий канала;
  • элемент <author>, указывающий владельца учетной записи;
  • элементы <openSearch> со сводными статистическими данными.

Внешний элемент <feed> содержит один или несколько элементов <entry>, каждый из которых представляет блог. Каждый элемент <entry> содержит более подробную информацию, включая название, описание, дату создания, дату последнего обновления и автора каждого блога. Кроме того, каждая запись включает в себя набор ссылок на каналы с заметками, шаблонами и параметрами настройки блога.

В в листинге 1 каждый блог ассоциируется с уникальным идентификатором блога. Он используется для создания URL каналов, связанных с блогом. Например, чтобы найти канал заметок конкретного блога, используйте URL, указанный в элементе <link rel='http://schemas.google.com/g/2005#post'... />. В листинге 2 показано, как может выглядеть канал заметок.

Листинг 2. Канал заметок Blogger
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
 xmlns:georss='http://www.georss.org/georss' 
 xmlns:thr='http://purl.org/syndication/thread/1.0'>
  <id>tag:blogger.com,1999:blog-12345BLOGIDHERE12345</id>
  <updated>2011-09-01T21:06:44.240-07:00</updated>
  <title type='text'>V Vaswani's Blog</title>
  <subtitle type='html'></subtitle>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://vvaswani.blogspot.com/feeds/posts/default'/>
  <link rel='self' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
  <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' 
   href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/default'/>
  <link rel='alternate' type='text/html' href='http://vvaswani.blogspot.com/'/>
  <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
  </author>
  <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
  <openSearch:totalResults>3</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
  <entry>
    <id>tag:blogger.com,1999:blog-12345BLOGIDHERE12345.post-
     12345POSTIDHERE12345</id>
    <published>2011-09-01T03:34:00.001-07:00</published>
    <updated>2011-09-01T21:06:44.258-07:00</updated>
    <title type='text'>My Third Post</title>
    <content type='html'>This is my third post
    <br /></content>
    <link rel='replies' type='application/atom+xml' 
     href='http://vvaswani.blogspot.com/feeds/12345POSTIDHERE12345/comments/default'
     title='Post Comments'/>
    <link rel='replies' type='text/html' 
     href='https://www.blogger.com/comment.g?
     blogID=12345BLOGIDHERE12345&postID=12345POSTIDHERE12345' 
     title='0 Comments'/>
    <link rel='edit' type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/
     default/12345POSTIDHERE12345'/>
    <link rel='self' type='application/atom+xml' 
     href='http://www.blogger.com/feeds/12345BLOGIDHERE12345/posts/
     default/12345POSTIDHERE12345'/>
    <link rel='alternate' type='text/html' 
     href='http://vvaswani.blogspot.com/2011/09/my-third-d.html' 
     title='My Third Post'/>
    <author>
    <name>V Vaswani</name>
    <email>noreply@blogger.com</email>
    </author>
    <thr:total>0</thr:total>
  </entry>
  ...
</feed>

Из листинга 2 следует, что канал заметок содержит набор элементов <entry>, каждый из которых соответствует одной заметке блога. Каждый элемент <entry> содержит:

  • заголовок, содержание и дату публикации заметки;
  • ссылки на общедоступный URL заметки, канал редактирования, канал комментариев и канал редактирования комментариев. Эти каналы используются для просмотра и редактирования заметки или комментариев к ней с помощью API Blogger Data.

У каждой заметки есть также уникальный идентификатор, называемый ID заметки, который находится в элементе <id> записи. Это составная строка, которая включает в себя идентификатор блога и идентификатор заметки в формате tag:blogger.com,1999:blog-BLOGID.post-POSTID. Например, в строке идентификации tag:blogger.com,1999:blog-1234.post-6789 идентификатор блога ― 1234, а идентификатор заметки ― 6789.


Получение блогов и заметок

Теперь, когда мы знаем, как получить доступ к блогу и каналам заметок посредством API, попробуем проделать то же самое с помощью PHP-приложения. Чтобы создать каналы в листингах 1 и 2, мы сначала вручную вошли в Blogger с учетной записью Google. Для получения и обработки каналов посредством PHP-приложения нужно выполнить ту же операцию аутентификации программным способом.

Написание процесса аутентификации вручную ― довольно сложная задача, требующая большого количества кода для учета различных сценариев, которые могут возникнуть во время типичной операции проверки подлинности. К счастью, в Zend Framework есть клиентская библиотека PHP Zend_Gdata, специально предназначенная для разработчиков, которые пытаются интегрировать PHP-приложения с Google Data API. Zend_Gdata обеспечивает удобный объектно-ориентированный интерфейс для API Google Data (см. ссылку для загрузки в разделе Ресурсы). Эта библиотека содержит большинство общих задач, включая проверку подлинности, и позволяет программисту сконцентрироваться на основных функциях своего приложения.

Установив библиотеку Zend Gdata, посмотрите на листинг 3. В нем показано, как обработать канал из листинга 1 и преобразовать его в Web-страницу со списком всех блогов зарегистрированного пользователя Blogger.

Листинг 3. Список блогов
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // получение списка всех блогов
  $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/default/blogs');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Blogs</h2>
    <ul>
      <?php foreach ($feed as $entry): ?>      
      <li>
        <a href="<?php 
         echo $entry->getLink('alternate')->getHref(); ?>">
         <?php echo $entry->getTitle(); ?> 
        </a>          
      </li>
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

Код из листинга 3 загружает библиотеки классов Zend и инициализирует экземпляр класса службы Zend_Gdata. Zend_Gdata использует объект Zend_Http_Client, который содержит данные, необходимые для проверки подлинности пользователя, и применяется для открытия соединения аутентификации со службой Blogger. Этот класс служит также для управления всем последующим взаимодействием с API Blogger Data.

Как только соединение проверки подлинности открыто, с помощью метода getFeed() извлекается список блогов. getFeed() принимает объект Zend_Gdata_Query, которому передается URL канала для получения списка блогов. Ответом на вызов API getFeed() служит XML-канала, как это было в листинге 1, который затем анализируется и преобразуется в PHP-объект. Записи в канале представлены как элементы массива, что позволяет:

  • выполнять итерации в пределах канала;
  • получать имена и URL отдельных блогов;
  • форматировать их для отображения в Web-браузере.

На рисунке 1 показан наблюдаемый результат.

Рисунок 1. Пример Web-страницы со списком блогов пользователя
Web-страница со списком блогов пользователя

Как отмечалось выше, каждый блог и каждая заметка в службе Blogger имеют уникальный идентификатор. Если знать уникальный идентификатор блога, можно сгенерировать URL соответствующего канала блога со списком всех заметок в этом блоге. Листинг 4 иллюстрирует процесс получения и обработки такого канала блога с помощью клиентской библиотеки Zend_Gdata.

Листинг 4. Список заметок блога
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // получение списка всех заметок в канале блога
  $query = new Zend_Gdata_Query(
   'http://www.blogger.com/feeds/YOUR-BLOG-ID-HERE/posts/default');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Posts</h2>
    <ul>
      <?php foreach ($feed as $entry): ?>      
      <li>
        <a href="<?php 
         echo $entry->getLink('alternate')->getHref(); ?>">
            <?php echo $entry->getTitle(); ?> 
        </a>          
      </li>
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

Как и в листинге 3, в листинге 4 сначала инициализируются библиотеки Zend и создается объект службы Zend_Gdata для зарегистрированного пользователя. Идентификатор блога применяется для создания URL канала блога, который преобразуется в объект Zend_Gdata_Query и передается в метод getFeed(). Затем полученный канал анализируется и обрабатывается обычным образом для получения списка всех заметок в указанном блоге. На рисунке 2 приведен пример выходных данных.

Рисунок 2. Web-страница со списком заметок в блоге пользователя
Web-страница со списком заметок в блоге пользователя

Объединив листинг 3 и листинг 4, можно получить список всех блогов и заметок в каждом блоге зарегистрированного пользователя. Комбинированный код приведен в листинге 5.

Листинг 5. Список блогов и заметок
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // создание массива
  $data = array();

  // получение списка всех сообщений во всех каналах блогов
  $query1 = new Zend_Gdata_Query('http://www.blogger.com/feeds/default/blogs');
  $feed1 = $service->getFeed($query1);
  foreach ($feed1 as $entry1) {
    $arr = explode('-', (string)$entry1->getId());
    $id = $arr[2];
    $query2 = new Zend_Gdata_Query(
     'http://www.blogger.com/feeds/'.$id.'/posts/default');
    $feed2 = $service->getFeed($query2);
    $blogArray = array(
      'title' => (string)$entry1->getTitle(), 
      'uri' => (string)$entry1->getLink('alternate')->getHref(),
      'posts' => array()
    );
    foreach ($feed2 as $entry2) {
      $postArray = array(
        'title' => (string)$entry2->getTitle(), 
        'uri' => (string)$entry2->getLink('alternate')->getHref()
      );
      $blogArray['posts'][] = $postArray;
    }
    $data[] = $blogArray;
  }
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Blogs and Posts</h2>
    <div id="results">
      <?php foreach ($data as $d): ?>      
      <ul>      
        <li><a href="<?php echo $d['uri']; ?>">
        <?php echo $d['title']; ?></a></li>
          <ul>
          <?php foreach ($d['posts'] as $p): ?>      
            <li><a href="<?php echo $p['uri']; ?>">
            <?php echo $p['title']; ?></a></li>
          <?php endforeach; ?>
          </ul>
      </ul>
      <?php endforeach; ?>
    </div>  
  </body>
</html>

В листинге 5 сначала запрашивается метаканал блогов и перебираются все его записи для извлечения уникальных идентификаторов каждого блога. Затем эти идентификаторы используются для составления URL канала блога, который запрашивается и обрабатывается для извлечения заголовка и URL каждой заметки. Вся эта информация хранится в иерархическом массиве, как показано в листинге 6.

Листинг 6. Иерархический массив
Array
(
  [0] => Array
  (
    [title] => V Vaswani's Blog
    [uri] => http://***.blogspot.com/
    [posts] => Array
    (
      [0] => Array
      (
        [title] => My Fourth Post
        [uri] => http://***.blogspot.com/2011/09/my-fourth-post.html
      )

      [1] => Array
      (
        [title] => My Third Post
        [uri] => http://***.blogspot.com/2011/09/my-third-d.html
      )

      [2] => Array
      (
        [title] => My Second Post
        [uri] => http://***.blogspot.com/2011/08/my-second-post.html
      )

      [3] => Array
      (
        [title] => My First Post
        [uri] => http://***.blogspot.com/2008/02/testing.html
      )
    )
  )

  [1] => Array
  (
    [title] => V Vaswani's Second Blog
    [uri] => http://***.blogspot.com/
    [posts] => Array
    (
      [0] => Array
      (
        [title] => My First Post in my Second Blog
        [uri] => http://***.blogspot.com/2011/09/my-first-post-in-my-second-blog.html
      )
    )
  )
)

Как только массив полностью сгенерирован, можно просто пройтись по нему и подготовить иерархический список блогов и заметок. На рисунке 3 приведен пример выходных данных.

Рисунок 3. Web-страница со списком блогов и заметок пользователя
Web-страница со списками пользователя

Добавление заметок в блог

Помимо извлечения существующих заметок, API Blogger Data позволяет зарегистрированным пользователям программно добавлять в блог новые. Создайте новый объект Zend_Gdata_App_Entry, введите заголовок и содержание, а затем разместите его в канале блога. Пример кода приведен в листинге 7.

Листинг 7. Добавление заметки в блог
<?php
if (isset($_POST['submit'])) {

  // загрузка библиотек Zend Gdata 
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata');
  Zend_Loader::loadClass('Zend_Gdata_Query');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  Zend_Loader::loadClass('Zend_Gdata_Feed');

  // задание учетных данных для аутентификации ClientLogin
  $user = "your-username@gmail.com";
  $pass = "your-password";

  // задание идентификатора блога
  $id = 'YOUR-BLOG-ID-HERE';

  try {
    // регистрация 
    // инициализация объекта службы
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'blogger');
    $service = new Zend_Gdata($client);

    // создание нового объекта записи
    // заполнение его данными    
    $uri = 'http://www.blogger.com/feeds/' . $id . '/posts/default';
    $entry = $service->newEntry();
    $entry->title = $service->newTitle($_POST['title']);
    $entry->content = $service->newContent($_POST['body']);
    $entry->content->setType('text');

    // сохранение записи на сервере
    // получение уникального идентификатора новой заметки
    $response = $service->insertEntry($entry, $uri);
    $arr = explode('-', $response->getId());
    $id = $arr[2];
    echo 'Successfully added post with ID: ' . $id;

  } catch (Exception $e) {
    die('ERROR:' . $e->getMessage());  
  }
}
?>
<html>
  <head></head>
  <body>
    <h2>Add New Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" 
       size="50" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"> </textarea> <br/>
      <input type="submit" name="submit" value="Post" />
    </form>
  </body>
</html>

В листинге 7 приведена простая Web-форма, которая позволяет вводить заголовок и тело заметки блога. После отправки формы сценарий загружает библиотеки классов Zend и создает объект службы. Затем сценарий использует метод newEntry() объекта службы для создания нового объекта записи, а методы newTitle() и newContent() ― для задания заголовка и содержания заметки блога из данных, введенных пользователем. Когда эти атрибуты заданы, новая заметка сохраняется на сервере Google с помощью метода insertEntry().

Пример формы приведен на рисунке 4.

Рисунок 4. Web-форма для добавления новой заметки
Web-форма для добавления новой заметки

Возвращаемое значение метода insertEntry() представляет собой запись, соответствующую только что созданной заметке. Теперь эта запись содержит уникальный идентификатор заметки, который можно извлечь и отобразить на странице. После сохранения новая заметка становится видимой в открытом блоге, а также появляется во всех каналах API этого блога.


Редактирование и удаление заметок

С помощью API Blogger Data можно удалять или редактировать существующие заметки. В обоих случаях, соответствующий запрос DELETE или PUT должен передаваться по URL редактирования заметки (см. пример в листинге 2). Обе эти операции могут выполнить только зарегистрированные пользователи.

Код, приведенный в листинге 8 , показывает, как удалить существующую заметку в блоге с помощью API, если идентификаторы блога и заметок уже есть.

Листинг 8. Удаление заметки из блога
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификаторов блога и заметки
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // задание URI записи, подлежащей удалению
  // получение от  <link rel=edit ... />
  $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
  $service->delete($uri);
  echo 'Successfully deleted post with ID: ' . $pid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

В листинге 8 для удаления указанной заметки из блога используется метод delete() объекта службы. Метод delete() принимает URL редактирования заметки и передает запрос DELETE по этому URL. После удаления заметка исчезает из открытого и частного блогов и из всех каналов API, которые ссылаются на нее.

Чтобы показать код обновления существующей заметки в блоге посредством API, снова предположим, что идентификаторы блога и заметки у нас уже есть, см. листинг 9.

Листинг 9. Редактирование заметки в блоге
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификаторов блога и заметки
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // задание URI редактируемой записи
  // получение от  <link rel=self ... />
  $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;

  // получение существующей записи
  // задание новых значений
  // сохранение
  $response = $service->get($uri);
  $entry = new Zend_Gdata_App_Entry($response->getBody());
  $entry->title = $service->newTitle("New title");
  $entry->content = $service->newContent("New content");
  $entry->content->setType('text');
  $service->updateEntry($entry);
  echo 'Successfully updated post with ID: ' . $pid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

Редактирование заметки в блоге посредством API ― двухэтапный процесс. Сначала нужно получить существующую заметку и преобразовать ее в объект Zend_Gdata_App_Entry. Затем можно использовать методы объекта службы, такие как newTitle() и newContent(), для редактирования записи и ее сохранения на сервере с использованием метода updateEntry().

Как и в случае метода insertEntry(), возвращаемым значением метода updateEntry() является запись, определяющая заметку, включая ее уникальный идентификатор и содержание. После сохранения отредактированная заметка становится видимой в открытом блоге, а также появляется во всех каналах API этого блога.


Работа с комментариями

Точно так же, как и сами заметки, можно добавлять, редактировать и удалять комментарии к ним. Обратите внимание, что в листинге 2 каждая запись заметки содержит ссылки на канал комментариев. Чтобы добавить новый комментарий, достаточно вставить запись в этот канал комментариев.

В листинге 10 показан процесс добавления нового комментария к заметке.

Листинг 10. Добавление нового комментария
<?php
// загрузка библиотек Zend Gdata require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификаторов блога и заметки
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // создание нового объекта записи
  // заполнение его данными    
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default";
  $entry = $service->newEntry();
  $entry->content = $service->newContent('This is a very interesting post.');
  $entry->content->setType('text');

  // сохранение записи на сервере
  // получение уникального идентификатора нового комментария
  $response = $service->insertEntry($entry, $uri);
  $arr = explode('/', $response->getEditLink()->href);
  $id = $arr[8];
  echo 'Successfully added comment with ID: ' . $id;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

Новый комментарий добавляется почти так же, как новая заметка; единственное отличие заключается в URL, по которому отправляется запрос (в данном случае это URL канала комментариев). Ответом на метод insertEntry() служит объект, соответствующий вновь добавленному комментарию. Этот объект можно проанализировать для получения уникального идентификатора комментария, который понадобится, если вы захотите удалить комментарий.

Если идентификатор комментария уже есть, можно воспользоваться кодом из листинга 11, чтобы программно удалить комментарий с помощью метода delete().

Листинг 11. Удаление комментария
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификаторов блога, заметки и комментария
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';
$cid = 'YOUR-COMMENT-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // задание URI записи, подлежащей удалению
  // получение от  <link rel=edit ... />
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default/$cid";
  $service->delete($uri);
  echo 'Successfully deleted comment with ID: ' . $cid;

} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

Тот же URL канала комментариев можно использовать для получения списка всех комментариев к заметке, как показано в листинге 12.

Листинг 12. Распечатка комментариев
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификаторов блога и заметки
$bid = 'YOUR-BLOG-ID-HERE';
$pid = 'YOUR-POST-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // получение списка всех комментариев к заметке
  $uri = "http://www.blogger.com/feeds/$bid/$pid/comments/default/";
  $query = new Zend_Gdata_Query($uri);
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head></head>
  <body>
    <h2>Comments</h2>
    <div id="results">
      <ul>
      <?php foreach ($feed as $entry): ?>      
        <?php $author = $entry->getAuthor(); ?>
        <li><?php echo $entry->getTitle(); ?> 
         - <?php echo $author[0]->getName(); ?> <br/>
        <?php echo date('d M Y H:i', strtotime($entry->getUpdated())); ?>
        </li>          
      <?php endforeach; ?>
    </ul>  
  </body>
</html>

Пример приложения: система управления контентом

Попробуем применить все это на практике и создать простое приложение, которое демонстрирует всю мощь API Blogger Data. Примером приложения служит менеджер Web-контента, который позволяет просматривать существующие заметки в блогах, редактировать или удалять их и добавлять новые. Редактирование выполняются в редакторе WYSIWYG на основе браузера и передается в Blogger через API Blogger Data.

Для начала загрузите и установите на свой сервер разработки редактор JavaScript TinyMCE (см. ссылку в разделе Ресурсы). Создайте сценарий, содержащий код, показанный в листинге 13.

Листинг 13. Управление содержанием блога
<?php
// загрузка библиотек Zend Gdata 
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Feed');

// задание учетных данных для аутентификации ClientLogin
$user = "your-username@gmail.com";
$pass = "your-password";

// задание идентификатора блога
$bid = 'YOUR-BLOG-ID-HERE';

try {
  // регистрация 
  // инициализация объекта службы
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'blogger');
  $service = new Zend_Gdata($client);

  // for add and edit operations
  if (isset($_POST['submit'])) {
    // при наличии идентификатора заметки:
    // редактирование заметки
    if (isset($_POST['pid'])) {      
      $arr = explode('-', $_GET['pid']);
      $pid = $arr[2];
      $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
      $response = $service->get($uri);
      $entry = new Zend_Gdata_App_Entry($response->getBody());
      $entry->title = $service->newTitle($_POST['title']);
      $entry->content = $service->newContent($_POST['body']);
      $entry->content->setType('text');
      $service->updateEntry($entry);
      echo 'Successfully updated post with ID: ' . $pid;    
    } else {
      // при отсутствии идентификатора заметки:
      // создание новой заметки
      // и заполнение ее данными    
      $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default';
      $entry = $service->newEntry();
      $entry->title = $service->newTitle($_POST['title']);
      $entry->content = $service->newContent($_POST['body']);
      $entry->content->setType('text');
      $response = $service->insertEntry($entry, $uri);
      $arr = explode('-', $response->getId());
      $id = $arr[2];
      echo 'Successfully added post with ID: ' . $id;  
    }
  }

  // для операций редактирования и удаления 
  if (isset($_GET['op'])) {
    // generate post URL
    $arr = explode('-', $_GET['pid']);
    $pid = $arr[2];
    $uri = 'http://www.blogger.com/feeds/' . $bid . '/posts/default/' . $pid;
    switch($_GET['op']) {
      case 'delete':
        // удаление заметки
        $service->delete($uri);
        echo 'Successfully deleted post with ID: ' . $pid;      
        break;
      case 'edit':
        // получение заметки для отображения в форме редактирования
        $response = $service->get($uri);
        $entry = new Zend_Gdata_App_Entry($response->getBody());
    }
  }

  // получение списка всех заметок в канале блога
  $query = new Zend_Gdata_Query(
   'http://www.blogger.com/feeds/'.$bid.'/posts/default');
  $feed = $service->getFeed($query);
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<html>
  <head>
    <script type="text/javascript" 
     src="tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
    <script type="text/javascript">
    tinyMCE.init({
            mode : "textareas",
            theme : "advanced",
            theme_advanced_buttons1 : "bold,italic,underline,|,justifyleft,
             justifycenter,justifyright,|,code,preview,|,forecolor,backcolor,|,sub,sup,
             |,fontsizeselect",
            theme_advanced_buttons2 : "cut,copy,paste,|,bullist,numlist,|,outdent,indent,
             |,undo,redo,|,link,unlink,anchor,image,|,removeformat",
            theme_advanced_buttons3 : "",      
            theme_advanced_toolbar_location : "top",
            theme_advanced_toolbar_align : "left",
            theme_advanced_statusbar_location : "bottom",
            theme_advanced_resizing : true
    });

    </script>
  </head>
  <body>
    <h2>View Posts</h2>
    <ul>
    <?php foreach ($feed as $e): ?>  
      <li><?php echo $e->getTitle(); ?> <br/>
      <a href="<?php 
      echo $e->getLink('alternate')->getHref(); ?>">View</a> 
       | <a href="?op=edit&pid=<?php echo $e->getId(); ?>">Edit</a>
       | <a href="?op=delete&pid=<?php echo $e->getId(); ?>">Delete
       </a>
      </li>
    <?php endforeach; ?>
    </ul>
    <a href="<?php echo $_SERVER['PHP_SELF']; ?>">
     Add a new post</a>
    <?php if (isset($_GET['op']) && $_GET['op'] == 'edit'): ?>
    <h2>Edit Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" size="50" 
       value="<?php echo $entry->title; ?>" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"><?php echo $entry->content; ?></textarea> <br/>
      <input type="hidden" name="pid" 
       value="<?php echo $entry->id; ?>" />
      <input type="submit" name="submit" value="Post" />
    </form>
    <?php else: ?>
    <h2>Add New Post</h2>
    <form method="post">
      Title: <br/> <input type="text" name="title" 
       size="50" /> <br/>
      Body: <br/> <textarea name="body" cols="40" 
       rows="10"> </textarea> <br/>
      <input type="submit" name="submit" value="Post" />
    </form>
    <?php endif; ?>
  </body>
</html>

На первый взгляд приведенный выше код может показаться сложным, но это всего лишь несколько условных операторов, обертывающих код, который мы уже рассмотрели. Вот его описание.

  • Сценарий начинается с загрузки библиотек классов Zend и задания учетных данных для аутентификации. Здесь же определяется идентификатор блога. Все последующие операции относятся только к указанному блогу.
  • Если параметры запроса отсутствуют, сценарий подключается к Blogger API и запрашивает список всех заметок указанного блога. Затем полученный канал обрабатывается, и отображается список заметок в виде HTML-списка.

    Каждое сообщение сопровождается тремя ссылками: для просмотра ( View), редактирования ( Edit) и удаления ( Delete) заметки. Ссылка View указывает на открытый URL заметки. Ссылки Edit и Delete просто вызывают сценарий повторно, передавая ему идентификатор выбранной заметки в виде параметра запроса GET.

  • После создания списка существующих заметок сценарий создает также Web-форму для добавления пользователем новых заметок. Эта форма содержит поле ввода одной строки текста (для заголовка) и область многострочного текста (для тела заметки).

    Редактор TinyMCE, который также инициализируется при загрузке страницы, автоматически преобразует текстовую область в поле редактирования такста WYSIWYG с элементами управления форматированием и гиперссылками.

  • Что происходит дальше, зависит от выбираемых пользователем операций.
    Если пользователь выбирает...то...
    добавление новой заметкиПосле того как Web-форма заполнена и передана, сценарий создает новый объект записи с помощью метода newEntry(), заполняет его введенными данными и сохраняет в блоге с помощью метода insertEntry().
    удаление существующей заметкиПо запрашиваемому URL извлекается идентификатор выбранной заметки, и с помощью идентификаторов блога и заметки составляется URL канала заметки. Затем заметка удаляется с помощью метода объекта службы delete().
    редактирование существующей заметкиПо запрашиваемому URL извлекается идентификатор выбранной заметки, и с помощью идентификаторов блога и заметки составляется URL канала заметки. Затем заметка извлекается с помощью метода объекта службы get(). Содержание заметки используется для предварительного заполнения Web-формы редактирования вместе со скрытым полем, содержащим уникальный идентификатор заметки.

    После того как пользователь внес изменения в содержание формы и отправил ее, скрытый идентификатор заметки используется для определения и обновления существующей заметки с помощью метода updateEntry().

Для простоты в этот сценарий не включены никакие проверки корректности ввода. В рабочей среде необходимо добавить проверку для обеспечения целостности и корректности данных, вводимых пользователями.

На рисунке 5 приведен пример системы управления содержанием блога.

Рисунок 5. Интерфейс управления содержанием блога
Интерфейс управления содержанием блога

Заключение

В этой статье объясняется, как интегрировать заметки блога Blogger непосредственно в PHP-приложение с помощью API Blogger Data и клиентской библиотеки Zend Gdata. Статья содержит введение в формат Web-каналов Blogger. Она также учит:

  • извлекать блоги, заметки и комментарии;
  • добавлять, редактировать и удалять заметки;
  • просматривать, добавлять и удалять комментарии.

API Blogger предоставляет мощный, не зависящий от формата механизм для интеграции содержания общедоступного блога в любое Web-приложение. Он отлично подходит для гибридных приложений или создания своего собственного пользовательского интерфейса для Blogger. Попрактикуйтесь и посмотрите, что можно сделать с его помощью.

Ресурсы

Научиться

Получить продукты и технологии

  • Zend Framework: загрузите библиотеку Zend, основанную на простоте, практических рекомендациях по объектно-ориентированному программированию, удобном корпоративном лицензировании и тщательно протестированной, гибкой базе кода.
  • Редактор TinyMCE : не зависящий от платформы HTML-редактор WYSIWYG на базе JavaScript.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Open source
ArticleID=824486
ArticleTitle=Интеграция контента Blogger с PHP-приложениями с помощью API Blogger Data
publish-date=07062012