Интеграция PHP-приложений с порталом Instagram

Часть 2. Использование API Instagram для ввода фотографий с портала Instagram в PHP-приложение

Instagram — это популярная служба обмена фотографиями, пользователи которой делают снимки с помощью своих смартфонов и публикуют их в Интернете. Разработчики приложений могут выполнять поиск этих фотографий, а также соответствующих комментариев и оценок посредством API-интерфейса Instagram на основе REST. Эта статья из двух частей знакомит читателя с API Instagram и показывает, каким образом его можно использовать с PHP для обращения к обширному хранилищу материалов, накопленных пользователями Instagram, и создания новаторских Web-приложений.

Введение

В первой части этой статьи я представил Instagram API, объяснил, как он работает, и познакомил читателя с основными элементами ответа Instagram API. Я также показал, как работать с Instagram API, применяя PHP для поиска и извлечения фотографий по меткам и местоположению и как получить полные метаданные фотографии, включая комментарии и оценки.

Примеры, приведенные в первой части статьи, относятся главным образом к тем оконечным точкам API, для которых не требуется авторизация пользователей по протоколу OAuth. Добавление OAuth делает возможным доступ через API-интерфейс к еще большему количеству информации. В этой второй и заключительной части я объясню, как добавить OAuth-аутентификацию к PHP-приложению и затем использовать маркер OAuth для обращения к защищенным оконечным точкам API, таким как авторизуемый канал доступа к фотографиям пользователя и его отношениям. Я также расскажу о некоторых сторонних библиотеках PHP, которые могут облегчить работу с API Instagram.


Поиск пользователей

Начнем с некоторых оконечных точек API Instagram, предоставляющих информацию о пользователях. Метод /users/search позволяет выполнять поиск пользователей Instagram по ключевым словам. Рассмотрим листинг 1, который иллюстрирует этот метод поиска в действии.

Листинг 1. Поиск пользователей
<html>
  <head></head>
  <body>
    <h1>Instagram User Search</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for:
      <input type="text" name="q" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // определение ключа и секретного ключа пользователя
      // доступно с консоли API Instagram
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // инициализация клиента
        $client = new Zend_Http_Client('https://api.instagram.com/v1/users/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('q', $_POST['q']);

        // получение и отображение пользователей
        $response = $client->request();
        $result = json_decode($response->getBody());
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) {
            echo '<li style="display: inline-block; padding: 25px">
              <img src="' . $item->profile_picture . '" /> <br/>' . 
              $item->username . ' (' . $item->full_name . ') </li>';
          }
          echo '</ul>';
        }
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
    ?>
  </body>
</html>

Сценарий, приведенный в листинге 1, создает Web-форму для ввода условий поиска. Затем он устанавливает соединение с Instagram API, обращается к методу /users/search с условиями поиска в качестве параметра и извлекает список подходящих пользователей. Для каждого пользователя сценарий отображает фото из профиля, псевдоним пользователя и его полное имя. Пример выходных данных показан на рисунке 1.

Рисунок 1. Поиск пользователей
Результаты поиска пользователей

Извлечение профилей пользователей

Кроме списка пользователей, API Instagram позволяет получить подробные сведения о конкретном пользователе с помощью метода /users/[user-id], который возвращает соответствующий JSON-документ. Для иллюстрации рассмотрим листинг 2, который дополняет листинг 1 поиском определенного пользователя с отображением любых обнаруженных деталей профиля.

Листинг 2. Извлечение профилей пользователей
<html>
  <head>
    <style>
    #info {
      float: left; 
      width: 300px;
      padding-right: 20px;
    }
    #image {
      float: left; 
      width: 320px;
      padding-right: 20px;
    }    
    </style>  
  </head>
  <body>
    <h1>Instagram User Profile</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for user:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <?php
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // определение ключа и секретного ключа пользователя
      // доступно с консоли API Instagram
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // инициализация клиента
        $client = new Zend_Http_Client('https://api.instagram.com/v1/users/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('q', $_POST['u']);
        $client->setParameterGet('count', '1');

        // поиск подходящих пользователей
        $response = $client->request();
        $result = json_decode($response->getBody());

        // извлечение идентификатора пользователя из результатов поиска
        if (count($result->data) != 1) {
          echo 'No matches found';
          exit;
        } else {
          $id = $result->data[0]->id;
        }

        // извлечение информации из профиля пользователя
        $client->setUri('https://api.instagram.com/v1/users/' . $id);
        $client->setParameterGet('client_id', $CLIENT_ID);
        $response = $client->request();
        $result = json_decode($response->getBody());
        $data = $result->data;  
    ?>    
        <div id="image">
          <h2>Image</h2>  
          <img src="<?php echo $result->data->profile_picture; ?>"
            /></a>
        </div>
        <div id="info">
          <h2>Meta</h2>  
          <strong>Username: </strong> 
          <?php echo $result->data->username; ?>
          <br/>
          <strong>Instagram id: </strong> 
          <?php echo $id; ?>
          <br/>
          <strong>Full name: </strong>
          <?php echo !empty($result->data->full_name) ? 
            $result->data->full_name : 'Not specified'; ?>
          <br/>
          <strong>Bio: </strong>
          <?php echo !empty($result->data->bio) ? 
            $result->data->bio : 'Not specified'; ?>
          <br/>
          <strong>Website: </strong>
          <?php echo !empty($result->data->website) ? 
            $result->data->website : 'Not specified'; ?>
          <br/>
          <strong>Instagram photos: </strong>
          <?php echo $result->data->counts->media; ?>
          <br/>
          <strong>Followers: </strong>
          <?php echo $result->data->counts->followed_by; ?>
          <br/>
          <strong>Following: </strong>
          <?php echo $result->data->counts->follows; ?>
          <br/>
        </div>
    <?php    
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
  ?>
  </body>
</html>

Присмотревшись к листингу 2, можно заметить, что он фактически выполняет два запроса к API Instagram. Первый извлекает список пользователей, соответствующих условиям поиска. Если найдено точное соответствие, то второй запрос заботится о получении данных по уникальному идентификатору пользователя. Так сделано потому, что оконечная точка /users/[user-id] принимает только идентификатор пользователя, но не его имя. Сначала необходимо найти подходящих пользователей, а затем извлечь нужный идентификатор и вставить его в запрос к оконечной точке /users/[user-id].

В ответ на запрос /users/[user-id] API выдает JSON-документ с подробной информацией об указанном пользователе. Эта информация содержит псевдоним пользователя Instagram, его полное имя, изображение из профиля, биографию и URL его персонального Web-сайта. В ней также указано количество фотографий, размещенных пользователем в Instagram, и число наблюдаемых и наблюдающих пользователей. Результат выполнения листинга 2 показан на рисунке 2.

Рисунок 2. Извлечение профилей пользователей
Извлечение профилей пользователей

Работа с автоканалом

Для доступа к оконечным точкам, фигурировавшим в двух предыдущих листингах, достаточно идентификатора пользователя. Однако в API Instagram есть и другие конечные точки, доступные только для запросов к API, подписанных по протоколу OAuth.

OAuth 2.0 ― это новая версия протокола OAuth 1.0. В отличие от OAuth 1.0, OAuth 2.0 (пока) не поддерживается средой Zend Framework, поэтому для обработки рабочего процесса OAuth 2.0 необходимо написать свой собственный код. Эта задача значительно упрощается библиотекой PHP-OAuth2 Пьеррика Чаррона и Аниса Бережье, которая предоставляется по лицензии GNU LGPL (см. ссылку в разделе Ресурсы). Библиотека PHP-OAuth2 делает введение поддержки OAuth 2.0 в собственное PHP-приложение относительно простым делом.

Для иллюстрации рассмотрим листинг 3, в котором библиотека PHP-OAuth2 используется для подключения к API Instagram, запроса доступа и отображения списка загруженных фотографий аутентифицированного пользователя, а также тех пользователей, за которыми наблюдает аутентифицированный пользователь (так называемый "автоканал" [self feed]). В этом примере используется метод API /users/self/feed.

Листинг 3. Извлечение автоканала
<?php
require('Client.php');
require('GrantType/IGrantType.php');
require('GrantType/AuthorizationCode.php');

const CLIENT_ID     = 'YOUR-CLIENT-ID';
const CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

const REDIRECT_URI           = 'http://localhost/dev/app.php';
const AUTHORIZATION_ENDPOINT = 'https://api.instagram.com/oauth/authorize';
const TOKEN_ENDPOINT         = 'https://api.instagram.com/oauth/access_token';

$client = new OAuth2\Client(CLIENT_ID, CLIENT_SECRET);
session_start();
if (!isset($_SESSION['ACCESS_TOKEN'])) {
  if (!isset($_GET['code'])) {
    $auth_url = $client->getAuthenticationUrl(AUTHORIZATION_ENDPOINT, 
      REDIRECT_URI, array('scope' => 'relationships'));
    header('Location: ' . $auth_url);
    die('Redirect');
  } else {
    $params = array('code' => $_GET['code'], 'redirect_uri' => REDIRECT_URI);
    $response = $client->getAccessToken(TOKEN_ENDPOINT, 'authorization_code', 
      $params);  
    $_SESSION['ACCESS_TOKEN'] = $response['result']['access_token'];
  }
} else {
  $client->setAccessToken($_SESSION['ACCESS_TOKEN']);
}
?>
<html>
  <head></head>
  <body>  
    <h1>Instagram User Feed</h1>  
    <?php
    try {
      // получение аутентифицированного канала пользователя
      $response = $client->fetch('https://api.instagram.com/v1/users/self/feed');
      $result = json_decode(json_encode($response['result']));

      // вывод изображений
      $data = $result->data;  
      if (count($data) > 0) {
        echo '<ul>';
        foreach ($data as $item) {
          echo '<li style="display: inline-block; padding: 25px">
            <a href="' . $item->link . '">
          <img src="' . $item->images->thumbnail->url . 
            '" /></a> <br/>';
          echo 'By: <em>' . $item->user->username . 
            '</em> <br/>';
          echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . 
            '<br/>';
          echo $item->comments->count . ' comment(s). ' . 
            $item->likes->count . ' likes. </li>';
        }
        echo '</ul>';
      }

    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

Первая часть листинга 3 — стандартный рабочий процесс OAuth 2.0, который безопасно перенаправляет пользователя на экран авторизации, а затем возвращает управление приложению, когда тот разрешил доступ. Обратите внимание, что маркер доступа OAuth 2.0, генерируемый этим сценарием, хранится в сеансе браузера, так что при последующих попытках доступа к защищенным оконечным точкам API авторизация не потребуется.

Параметр scope определяет область авторизации. В данном случае в дополнение к области по умолчанию запрашивается область relationships (отношения), потому что некоторые из примеров, приведенных в этой статье, демонстрируют способы изменения отношений между пользователями.

Маркер доступа OAuth 2.0, порожденный этим процессом, прикреплен к объекту клиента OAuth2, который затем применяется для запроса автоканала пользователя. JSON-ответ на этот запрос анализируется, как описано в первой части статьи, и динамически генерируется Web-страница с фотографиями аутентифицированного пользователя и тех, за кем он наблюдает. На рисунке 3 приведен пример такой страницы.

Рисунок 3. Отображение фотографий из автоканала
Фотографии из автоканала

Поиск фотографий пользователя

В листинге 3 продемонстрирован автоканал пользователя — канал фотографий, загруженных пользователем и теми, за кем он наблюдает. Но что, если вас интересуют только фотографии определенного пользователя? Такой поиск тоже возможен, с помощью оконечной точки API /users/[user-id]/media/recent, которая возвращает канал доступа к последним фотографиям, загруженным определенным пользователем.

Загвоздка в том, что оконечная точка /users/[user-id]/media/recent принимает только идентификатор пользователя, поэтому, как и в листинге 2, нужно сначала найти нужного пользователя с помощью оконечной точки /users/search. Затем идентификатор соответствующего пользователя применяется для запроса к оконечной точке /users/[user-id]/media/recent. Листинг 4 иллюстрирует этот процесс.

Листинг 4. Поиск фотографий пользователя
<?php
require_once('oauth-instagram-bootstrap.php');
?>
<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by User</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for user:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <?php
      try {
        // поиск подходящего пользователя
        $response = $client->fetch('https://api.instagram.com/v1/users/search', 
          array('count' => 1, 'q' => $_POST['u']));
        $result = json_decode(json_encode($response['result']));

        if (count($result->data) != 1) {
          echo 'No matches found';
          exit;
        } else {
          $id = $result->data[0]->id;
        }

        // получение недавно загруженных изображений
        $response = $client->fetch('https://api.instagram.com/v1/users/' . 
          $id . '/media/recent');
        $result = json_decode(json_encode($response['result']));

        // вывод изображений
        $data = $result->data;  
        if (count($data) > 0) {
          echo '<ul>';
          foreach ($data as $item) { 
            echo '<li style="display: inline-block; padding: 25px">
              <a href="' . $item->link . '">
            <img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . 
              '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . 
              '<br/>';
            echo $item->comments->count . ' comment(s). ' . 
              $item->likes->count . ' likes. </li>';
          }
          echo '</ul>';
        }

      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }
  ?>
  </body>
</html>

Рисунок 4 демонстрирует результаты поиска.

Рисунок 4. Поиск фотографий пользователя
Поиск фотографий пользователя

В листинге 4 ответ на запрос к оконечной точке /users/[user-id]/media/recent содержит набор фотографий, загруженных указанным пользователем. Ничего не стоит перебрать этот набор и для каждой фотографии вывести эскиз, основные метаданные, количество обращений и оценку.

Обратите внимание, что в листинге 4, а также в последующих примерах общий код рабочего процесса авторизации OAuth 2.0 хранится в отдельном файле начальной загрузки, который указан в верхней части каждого сценария. Это делается для уменьшения длины листингов в этой статье и удобочитаемости.


Проверка отношений пользователя

Как и другие социальные сети, Instagram позволяет пользователям наблюдать за другими пользователями. В API Instagram есть две оконечные точки для получения информации об отношениях пользователя: /users/[user-id]/follows и /users/[user-id]/followed-by. При указании пользователя эти оконечные точки возвращают список других пользователей, которые наблюдает за этим пользователем или за которыми наблюдает он. Листинг 5 иллюстрирует эти конечные точки в действии.

Листинг 5. Проверка отношений пользователя
<html>
  <head>
    <style>
    #follows {
      float: left; 
      width: 400px;
      padding-right: 20px;
    }
    #followers {
      float: left; 
      width: 400px;
      padding-right: 20px;
    }    
    </style>  
  </head>
  <body>
    <h1>Instagram User Relationships</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for user:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
      <h2>Relationships for '<?php echo $_POST['u']; ?>'</h2>
    <?php
      // userid 262796303
      require_once 'Zend/Loader.php';
      Zend_Loader::loadClass('Zend_Http_Client');

      // определение ключа и секретного ключа пользователя
      // доступно с консоли API Instagram
      $CLIENT_ID = 'YOUR-CLIENT-ID';
      $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

      try {
        // инициализация клиента
        $client = new Zend_Http_Client('https://api.instagram.com/v1/users/search');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $client->setParameterGet('q', $_POST['u']);

        // поиск подходящих пользователей
        $response = $client->request();
        $result = json_decode($response->getBody());

        // извлечение идентификатора пользователя из результатов поиска
        if (count($result->data) != 1) {
          echo 'No matches found';
          exit;
        } else {
          $id = $result->data[0]->id;
        }

        // за кем наблюдает пользователь
        $client->setUri('https://api.instagram.com/v1/users/' . 
          $id . '/follows');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $response = $client->request();
        $result = json_decode($response->getBody());
        $follows = $result->data;
        unset($result);

        // кто наблюдает за пользователем
        $client->setUri('https://api.instagram.com/v1/users/' . 
          $id . '/followed-by');
        $client->setParameterGet('client_id', $CLIENT_ID);
        $response = $client->request();
        $result = json_decode($response->getBody());
        $followers = $result->data;  

    ?>    
        <div id="follows">
          <h2>Follows</h2>
          <?php
          if (count($follows) > 0) {
            echo '<ul>';
            foreach ($follows as $item) {
              echo '<li style="display: inline-block; padding: 25px">
                <img src="' . $item->profile_picture . '" /> <br/>' . 
                $item->username . ' (' . $item->full_name . ') </li>';
            }
            echo '</ul>';
          } else {
            echo 'Not following anyone';
          }
          ?>
        </div>

        <div id="followers">
          <h2>Followers</h2>
          <?php
          if (count($followers) > 0) {
            echo '<ul>';
            foreach ($followers as $item) {
              echo '<li style="display: inline-block; padding: 25px">
                <img src="' . $item->profile_picture . '" /> <br/>' . 
                $item->username . ' (' . $item->full_name . ') </li>';
            }
            echo '</ul>';
          } else {
            echo 'No followers';
          }
          ?>
        </div>

    <?php    
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }  
  ?>
  </body>
</html>

Листинг 5 создает Web-форму, которая позволяет вводить имя пользователя Instagram. После отправки формы листинг 5 сначала обращается к оконечной точке API /users/search, чтобы найти идентификатор нужного пользователя, а затем внедряет этот идентификатор в запросы к оконечным точкам /users/[user-id]/follows и /users/[user-id]/followed-by. JSON-документы, полученные от этих оконечных точек, используются для отображения списков наблюдения, каждый из которых содержит фотографии из профилей пользователей, их псевдонимы и полные имена. Пример выходных данных приведен на рисунке 5.

Рисунок 5. Отображение отношений пользователя
Отображение отношений пользователя

Редактирование отношений пользователя

Помимо предоставления информации об отношениях пользователя, API Instagram позволяет вносить изменения в эти отношения. Защищенная оконечная точка /users/[user-id]/relationship принимает POST-запросы на действия follow (наблюдать), unfollow (отменить наблюдение), block (блокировать), unblock (разблокировать), approve (одобрить) или deny (запретить) и выполняет эти действия для отношений между указанным пользователем и текущим авторизованным пользователем. Это позволяет, например, регулировать отношения наблюдения между пользователями прямо через API.

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

Листинг 6. Редактирование отношений пользователей
<?php
require_once('oauth-instagram-bootstrap.php');
?>
<html>
  <head>
    <style>
    #follows {
      float: left; 
      width: 400px;
      padding-right: 20px;
    }
    #followers {
      float: left; 
      width: 400px;
      padding-right: 20px;
    }    
    </style>  
  </head>
  <body>
    <h1>Follow on Instagram</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Enter name of user to follow:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
      // поиск подходящего пользователя
      $response = $client->fetch('https://api.instagram.com/v1/users/search', 
        array('q' => $_POST['u']));
      $result = json_decode(json_encode($response['result']));

      if (count($result->data) != 1) {
        echo 'No matches found';
        exit;
      } else {
        $id = $result->data[0]->id;
      }

      // получение недавно загруженных изображений
      $response = $client->fetch('https://api.instagram.com/v1/users/' . 
        $id . '/relationship', 
        array('action' => 'follow'), 'POST');
      $result = json_decode(json_encode($response['result']));
      print_r($result); die;
    }  
  ?>
  </body>
</html>

В листинге 6 сначала выполняется поиск пользователя по имени, извлекается соответствующий идентификатор пользователя Instagram, а затем генерируется запрос POST к оконечной точке /users/[user-id]/relationship с параметром действия follow, чтобы установить отношения наблюдения между авторизованным пользователем и целевым пользователем.


Применение сторонних библиотек (1)

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

Одна из таких библиотек ― PHP Instagram API Галена Гровера, которая обеспечивает оболочку PHP 5.3+ для API Instagram (см. ссылку в разделе Ресурсы). Эта библиотека содержит набор классов, которые обеспечивают общие функциональные возможности, облегчающие работу с Instagram-объектами, такими как фотографии, пользователи, теги и комментарии. Рассмотрим листинг 7, в котором показано, как использовать эту библиотеку для получения наиболее популярных фотографий из Instagram.

Листинг 7. Получение популярных изображений с помощью библиотеки PHP Instagram API
<html>
  <head></head>
  <body>  
    <h1>Popular on Instagram</h1>  
    <?php
    // настройка автозагрузчика
    function app_autoloader($class) {
      include './' . $class . '.php';
    }
    spl_autoload_register('app_autoloader');

    // определение ключа и секретного ключа пользователя
    // доступно с консоли API Instagram
    $CLIENT_ID = 'YOUR-CLIENT-ID';
    $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

    // Инициализация клиента
    try {
      $instagram = new Instagram\Instagram;
      $instagram->setClientID($CLIENT_ID);

      // получение и отображение популярных изображений
      $media = $instagram->getPopularMedia();
      $data = $media->getData();
      if ($media->count() > 0) {
        echo '<ul>';
        foreach ($data as $item) {
          echo '<li style="display: inline-block; padding: 25px">
            <a href="' . $item->link . '"><img src="' . 
            $item->images->thumbnail->url . 
            '" /></a> <br/>';
          echo 'By: <em>' . $item->user->username . 
            '</em> <br/>';
          echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . '<br/>';
          echo $item->comments->count . ' comment(s). ' . 
            $item->likes->count . ' likes. </li>';
        }
        echo '</ul>';
      }
    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

Листинг 7 начинается с создания автозагрузчика, который автоматически загружает классы библиотеки по мере необходимости. Затем он инициализирует экземпляр класса Instagram, устанавливает идентификатор клиента и вызывает метод объекта getPopularMedia(), чтобы получить от Instagram список популярных фотографий. Метод getPopularMedia() возвращает объект MediaCollection с коллекцией медиаобъектов. Теперь легко перебрать эту коллекцию и получить подробную информацию о каждой фотографии для отображения на Web-странице. Результат показан на рисунке 6.

Рисунок 6. Получение популярных изображений
Получение популярных изображений

Библиотека PHP Instagram API поддерживает OAuth-запросы и содержит встроенные методы оболочки для защищенных оконечных точек API. Для иллюстрации рассмотрим листинг 8, в котором листинг 4 воссоздается с помощью библиотеки PHP Instagram API.

Листинг 8. Поиск фотографий пользователя с помощью библиотеки PHP Instagram API
<?php
// настройка автозагрузчика
function app_autoloader($class) {
  include './' . $class . '.php';
}
spl_autoload_register('app_autoloader');

// начало сеанса
session_start();

// настройка аутентификации
$config = array(
  'client_id'         => 'YOUR-CLIENT-ID',
  'client_secret'     => 'YOUR-CLIENT-SECRET',
  'redirect_uri'      => 'http://localhost/dev/app.php',
);

// проверка подлинности
if (!isset( $_SESSION['instagram_access_token'] ) ) {
  $auth = new Instagram\Auth($config);
  if (isset($_GET['code'])) {
      $_SESSION['instagram_access_token'] = $auth->getAccessToken( $_GET['code'] );
      header( 'Location: ' . REDIRECT_AFTER_AUTH );
      exit;
  } else {
    $auth->authorize();
  }
  exit;
}
?>
<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by User</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for user:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
    ?>
    <?php
      try {      
        // настройка клиента
        $instagram = new Instagram\Instagram;
        $instagram->setAccessToken($_SESSION['instagram_access_token']);

        // поиск подходящего пользователя
        $user = $instagram->getUserByUsername($_POST['u']);
        $media = $user->getMedia();  
        if ($media->count() > 0) {
          echo '<ul>';
          foreach ($media->getData() as $item) {
            echo '<li style="display: inline-block; padding: 25px">
              <a href="' . $item->link . '">
            <img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . 
              '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . 
              '<br/>';
            echo $item->comments->count . ' comment(s). ' . 
              $item->likes->count . ' likes. </li>';
          }
          echo '</ul>';
        }
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }
  ?>
  </body>
</html>

Как видите, листинг 8 значительно короче и нагляднее, чем листинг 4. После реализации необходимого процесса OAuth он запрашивает имя пользователя, а затем применяет метод getUserByUsername() для получения сведений об объекте User. Объект User предоставляет объект getMedia(), который возвращает коллекцию последних фотографий, загруженных этим пользователем. Эту коллекцию можно обработать, чтобы вывести эскизы всех загруженных фотографий, как показано на рисунке 4.


Применение сторонних библиотек (2)

Другая библиотека, разработанная Кристианом Мецем, также предоставляет простой в применении PHP-класс для работы с API Instagram (см. ссылку в разделе Ресурсы). В листинге 9 приведен пример ее применения для получения популярных изображений из Instagram.

Листинг 9. Получение популярных изображений с помощью библиотеки Instagram-PHP-API
<html>
  <head></head>
  <body>  
    <h1>Popular on Instagram</h1>  
    <?php
    require 'instagram.class.php';

    // определение ключа и секретного ключа пользователя
    $CLIENT_ID = 'YOUR-CLIENT-ID';
    $CLIENT_SECRET = 'YOUR-CLIENT-SECRET';

    // инициализация клиента
    try {
      $instagram = new Instagram($CLIENT_ID);

      // получение и отображение популярных изображений
      $media = $instagram->getPopularMedia();

      if (count($media->data) > 0) {
        echo '<ul>';
        foreach ($media->data as $item) {
          echo '<li style="display: inline-block; padding: 25px">
            <a href="' . $item->link . '"><img src="' . 
            $item->images->thumbnail->url . 
            '" /></a> <br/>';
          echo 'By: <em>' . $item->user->username . 
            '</em> <br/>';
          echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . 
            '<br/>';
          echo $item->comments->count . ' comment(s). ' . 
            $item->likes->count . ' likes. </li>';
        }
        echo '</ul>';
      }
    } catch (Exception $e) {
      echo 'ERROR: ' . $e->getMessage() . print_r($client);
      exit;
    }
    ?>
  </body>
</html>

Листинг 9 начинается с загрузки файла класса, затем создается экземпляр объекта Instagram и с помощью метода getPopularMedia() этого объекта извлекается список популярных фотографий. Этот метод внутренне обращается к оконечной точке /media/popular, получает ответ JSON и расшифровывает его. Результирующий объект можно обработать для отображения списка популярных фото, что приведет к тому же результату, что и в листинге 7.

С помощью этой библиотеки также можно воссоздать листинг 8, как показано в листинге 10.

Листинг 10. Поиск фотографий по пользователю с помощью Instagram-PHP-API
<?php
// включение класса
require 'instagram.class.php';

// определение учетных данных
$config = array(
  'apiKey'        => 'YOUR-CLIENT-ID',
  'apiSecret'     => 'YOUR-CLIENT-SECRET',
  'apiCallback'   => 'http://localhost/dev/app.php',
);

// инициализация клиента
session_start();
$instagram = new Instagram($config);

// проверка подлинности
if (!isset($_SESSION['IACCESS_TOKEN'])) {
  if (!isset($_GET['code'])) {
    $auth_url = $instagram->getLoginUrl();
    header('Location: ' . $auth_url);
    die('Redirect');
  } else {
    $data = $instagram->getOAuthToken($_GET['code']);  
    $_SESSION['IACCESS_TOKEN'] = $data;
    $instagram->setAccessToken($_SESSION['IACCESS_TOKEN']);
  }
} else {
  $instagram->setAccessToken($_SESSION['IACCESS_TOKEN']);
}

?>
<html>
  <head></head>
  <body>
    <h1>Instagram Photo Search by User</h1>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" 
      action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for user:
      <input type="text" name="u" /> 
      <input type="submit" name="submit" value="Search" />      
    </form>
    <?php
    } else {
      try {      
        // поиск подходящего пользователя
        $user = $instagram->searchUser($_POST['u']);

        // поиск фотографий пользователя
        $media = $instagram->getUserMedia($user->data[0]->id);  
        if (count($media->data) > 0) {
          echo '<ul>';
          foreach ($media->data as $item) {
            echo '<li style="display: inline-block; padding: 25px">
              <a href="' . $item->link . '">
            <img src="' . $item->images->thumbnail->url . 
              '" /></a> <br/>';
            echo 'By: <em>' . $item->user->username . 
              '</em> <br/>';
            echo 'Date: ' . date ('d M Y h:i:s', $item->created_time) . 
              '<br/>';
            echo $item->comments->count . ' comment(s). ' . 
              $item->likes->count . ' likes. </li>';
          }
          echo '</ul>';
        }
      } catch (Exception $e) {
        echo 'ERROR: ' . $e->getMessage() . print_r($client);
        exit;
      }
    }
  ?>
  </body>
</html>

Листинг 10, как и листинг 8, позволяет искать в Instagram фотографии определенных пользователей. Она начинается с вызова метода searchUser() объекта Instagram и передачи ему имени пользователя, указанного в Web-форме. Затем идентификатор пользователя из полученной записи пользователя передается в метод getUserMedia(), который возвращает список последних фотографий, загруженных этим пользователем.


Заключение

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

Ресурсы

Научиться

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

  • Zend Framework: загрузите эту популярную платформу для высокопроизводительных PHP-приложений.
  • Библиотека PHP OAuth 2.0: загрузите легкую PHP-оболочку для протокола OAuth 2.0 (на основе версии OAuth 2.0 Authorization Protocol draft-ietf-oauth-v2-15).
  • Библиотека PHP Instagram API (1): загрузите оболочку для API Instagram на основе PHP 5.3+.
  • Библиотека PHP Instagram API (2): загрузите простой в применении PHP-класс для обращения к API Instagram Instagram-PHP-API Кристиана Меца.

Обсудить

Комментарии

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, Web-архитектура
ArticleID=931051
ArticleTitle=Интеграция PHP-приложений с порталом Instagram
publish-date=05222013