Поначалу OAuth может оказаться сложной задачей, чтобы обернуть голову, но теперь, когда API-интерфейс Twitter требует его использования, его необходимо понять, прежде чем создавать приложение Twitter. Это руководство познакомит вас с OAuth и проведет вас через процесс создания базового приложения.
Вступление
В этом уроке мы будем создавать простое приложение, которое позволит пользователям применять различные эффекты к своему аватару в Твиттере. Чтобы работать с API Twitter, мы должны использовать OAuth, чтобы авторизовать наше приложение для отправки запросов от имени пользователя.
Наш поток приложений будет примерно таким:
- Пользователю предлагается связаться с Twitter.
- Пользователю предоставляется список аватаров предварительного просмотра на выбор.
- После выбора пользователю предоставляется экран подтверждения, показывающий исходный и новый аватар для сравнения. Пользователю также предлагается отправить твит.
- После подтверждения пользователем приложение создает и загружает измененный аватар в Twitter, и отображается страница успеха.
Настроить
Для начала нам нужно настроить наш исходный каталог. Нам нужен каталог lib
для наших файлов библиотеки (классов) PHP, каталог tmp
для хранения временных файлов (это необходимо для записи на сервере), каталог css
для нашей таблицы стилей и каталог img
для любых изображений.
Вот как должно выглядеть ваше дерево каталогов:
- руководство
- CSS
- IMG
- Lib
- TMP (доступный для записи)
Зарегистрируйте вашу заявку
Чтобы использовать OAuth, вам потребуется так называемый ключ и секретный ключ пользователя для идентификации вашего приложения. Чтобы получить их, вы должны зарегистрировать приложение в Twitter, выполнив следующие действия.
Перейдите на страницу регистрации , войдите в систему, если это необходимо. Вас приветствует форма, изображенная ниже:
Заполните форму с подробной информацией о вашем приложении. В нашем случае Тип приложения — Браузер, и нам нужно установить URL обратного вызова по умолчанию. Этот URL может быть любым, если он является допустимым форматом. Мы будем переопределять обратный вызов в нашем коде, поэтому не критично, что это реальный URL. Тип доступа по умолчанию должен быть для чтения и записи .
Как только вы зарегистрируетесь и примете условия, вам будет представлена информация о вашем новом заявлении. Важные детали, которые нам нужны, это ключ Consumer и Consumer secret , который должен выглядеть примерно так:
Загрузите библиотеку tmhOAuth
Мы будем использовать библиотеку для обработки всех деталей, стоящих за выполнением запросов OAuth. В этом руководстве мы будем использовать библиотеку @themattharris ‘ tmhOAuth , которая поддерживает загрузку файлов.
- Скачать tmhOAuth с GitHub
- Извлеките tmhOAuth.php в каталог lib, который мы создали ранее
Аутентификация
Аутентификация с помощью OAuth в основном состоит из трех этапов. Более подробное объяснение см. На этой странице по аутентификации в Twitter, но вот краткое изложение:
- Приложение получает токен запроса. На первом этапе наше приложение идентифицирует себя в Twitter (используя ключ потребителя) и получает токен запроса . Нам нужно сохранить этот токен запроса на потом.
- Пользователь авторизует приложение в Twitter. Теперь пользователю необходимо отправить его в Twitter, чтобы предоставить нашему приложению доступ к его учетной записи. После этого пользователь отправляется обратно на URL обратного вызова, указанный приложением.
- Приложение обменивает токен запроса на токен доступа. Теперь, когда наше приложение было одобрено, оно может обменять токен запроса с шага 1 на токен доступа . Когда у нас есть токен доступа, наше приложение может взаимодействовать с API Twitter от имени пользователя.
Итак, начнем с некоторого кода. Мы TwitterApp
все задачи аутентификации в классе под названием TwitterApp
. Начните со следующего кода в новом файле с именем lib/TwitterApp.php
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<?php
class TwitterApp {
/**
* This variable holds the tmhOAuth object used throughout the class
*
* @var tmhOAuth An object of the tmhOAuth class
*/
public $tmhOAuth;
/**
* User’s Twitter account data
*
* @var array Information on the current authenticated user
*/
public $userdata;
/**
* Authentication state
*
* Values:
* — 0: not authed
* — 1: Request token obtained
* — 2: Access token obtained (authed)
*
* @var int The current state of authentication
*/
protected $state;
/**
* Initialize a new TwitterApp object
*
* @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
*/
public function __construct(tmhOAuth $tmhOAuth) {
// save the tmhOAuth object
$this->tmhOAuth = $tmhOAuth;
}
}
|
Здесь мы создали три свойства и простой конструктор. Свойство $tmhOAuth
будет объектом tmhOAuth, который будет использоваться во всем классе. Свойство $userdata
будет содержать объект, содержащий информацию о пользователе, такую как его имя пользователя и статус в Twitter. Свойство $state
отслеживает текущее состояние аутентификации.
Конструктор просто принимает объект tmhOAuth и назначает его свойству $tmhOAuth
.
Шаг 1: Получить токен запроса
Вот метод для получения токена запроса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/**
* Obtain a request token from Twitter
*
* @return bool False if request failed
*/
private function getRequestToken() {
// send request for a request token
$this->tmhOAuth->request(«POST», $this->tmhOAuth->url(«oauth/request_token», «»), array(
// pass a variable to set the callback
‘oauth_callback’ => $this->tmhOAuth->php_self()
));
if($this->tmhOAuth->response[«code»] == 200) {
// get and store the request token
$response = $this->tmhOAuth->extract_params($this->tmhOAuth->response[«response»]);
$_SESSION[«authtoken»] = $response[«oauth_token»];
$_SESSION[«authsecret»] = $response[«oauth_token_secret»];
// state is now 1
$_SESSION[«authstate»] = 1;
// redirect the user to Twitter to authorize
$url = $this->tmhOAuth->url(«oauth/authorize», «») .
header(«Location: ‘ . $url);
exit;
}
return false;
}
|
Чтобы понять первую часть, вам нужно знать о tmhOAuth::request()
. Этот метод позволяет нам сделать HTTP-запрос с поддержкой OAuth, и он имеет следующее использование:
tmhOAuth::request($method, $url[, $params[, $useauth[, $multipart]]])
-
string $method
—string $method
запроса (GET, POST и т. д.) -
string $url
— URL для доступа -
array $params
(необязательно) — ассоциативный массив параметров для включения в запрос -
bool $useauth
(необязательно, по умолчанию true) — Требуется ли аутентификация? -
bool $multipart
(необязательно, по умолчанию false) — установите значение true для загрузки файлов
Для параметра $url
мы используем метод tmhOAuth::url()
для создания URL-адреса на основе метода API, который мы вызываем:
tmhOAuth::url($request[, $format])
-
string $request
— метод API (без расширения) -
string $format
(необязательно, по умолчанию ‘json «) — желаемый формат ответа (JSON, XML и т. д.)
Теперь, когда вы знакомы с этими методами, мы должны сделать запрос POST к методу API oauth / request_token . Это вернет данные OAuth в специальном формате, поэтому нам нужно установить пустой формат при использовании tmhOAuth::url()
. Нам также нужно передать переменную с именем oauth_callback
, куда пользователь вернется после авторизации в Twitter. Мы будем использовать метод tmhOAuth::php_self()
для ссылки на текущую страницу. Вот этот код снова:
1
2
3
4
5
|
// send request for a request token
$this->tmhOAuth->request(«POST», $this->tmhOAuth->url(«oauth/request_token», «»), array(
// pass a variable to set the callback
‘oauth_callback’ => $this->tmhOAuth->php_self()
));
|
Как только мы сделаем запрос, ответ сохраняется в виде массива в tmhOAuth::response
со следующими ключевыми частями данных:
-
code
— код ответа HTTP -
response
— возвращены фактические данные -
headers
— заголовки ответа
Поэтому следующая часть нашего кода проверяет код ответа (200 означает успех), а затем помещает полученные oauth_token
и oauth_token_secret
в переменные сеанса, так как они понадобятся нам позже. Они извлекаются из данных ответа с помощью tmhOAuth::extract_params()
, который возвращает массив данных, содержащихся в ответе. Мы также устанавливаем authstate
сеанса authstate
чтобы authstate
что мы находимся на следующем этапе аутентификации. Вот код:
01
02
03
04
05
06
07
08
09
10
|
if($this->tmhOAuth->response[«code»] == 200) {
// get and store the request token
$response = $this->tmhOAuth->extract_params($this->tmhOAuth->response[«response»]);
$_SESSION[«authtoken»] = $response[«oauth_token»];
$_SESSION[«authsecret»] = $response[«oauth_token_secret»];
// state is now 1
$_SESSION[«authstate»] = 1;
}
|
После этого мы должны перенаправить пользователя на URL-адрес oauth / authorize , включая oauth_token
в параметре GET. Вот этот код снова:
1
2
3
4
|
// redirect the user to Twitter to authorize
$url = $this->tmhOAuth->url(«oauth/authorize», «») .
header(«Location: ‘ . $url);
exit;
|
Шаг 2: Получить токен доступа
Вот способ обмена нашего токена запроса на токен доступа:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/**
* Obtain an access token from Twitter
*
* @return bool False if request failed
*/
private function getAccessToken() {
// set the request token and secret we have stored
$this->tmhOAuth->config[«user_token»] = $_SESSION[«authtoken»];
$this->tmhOAuth->config[«user_secret»] = $_SESSION[«authsecret»];
// send request for an access token
$this->tmhOAuth->request(«POST», $this->tmhOAuth->url(«oauth/access_token», «»), array(
// pass the oauth_verifier received from Twitter
‘oauth_verifier’ => $_GET[«oauth_verifier»]
));
if($this->tmhOAuth->response[«code»] == 200) {
// get the access token and store it in a cookie
$response = $this->tmhOAuth->extract_params($this->tmhOAuth->response[«response»]);
setcookie(«access_token», $response[«oauth_token»], time()+3600*24*30);
setcookie(«access_token_secret», $response[«oauth_token_secret»], time()+3600*24*30);
// state is now 2
$_SESSION[«authstate»] = 2;
// redirect user to clear leftover GET variables
header(«Location: ‘ . $this->tmhOAuth->php_self());
exit;
}
return false;
}
|
Сначала мы устанавливаем user_token
и user_secret
в tmhOAuth::config
на токен запроса, который мы получили ранее.
1
2
3
|
// set the request token and secret we have stored
$this->tmhOAuth->config[«user_token»] = $_SESSION[«authtoken»];
$this->tmhOAuth->config[«user_secret»] = $_SESSION[«authsecret»];
|
Следующая часть — это то, где мы делаем запрос POST к oauth / access_token . Мы передаем oauth_verifier
мы получили в переменной GET, в качестве параметра в этом запросе.
1
2
3
4
5
|
// send request for an access token
$this->tmhOAuth->request(«POST», $this->tmhOAuth->url(«oauth/access_token», «»), array(
// pass the oauth_verifier received from Twitter
‘oauth_verifier’ => $_GET[«oauth_verifier»]
));
|
Twitter ответит токеном доступа и секретом, который нам нужно сохранить для любых будущих запросов. Таким образом, следующий фрагмент кода берет их и сохраняет каждый в куки, а затем устанавливает состояние в 2.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
if($this->tmhOAuth->response[«code»] == 200) {
// get the access token and store it in a cookie
$response = $this->tmhOAuth->extract_params($this->tmhOAuth->response[«response»]);
setcookie(«access_token», $response[«oauth_token»], time()+3600*24*30);
setcookie(«access_token_secret», $response[«oauth_token_secret»], time()+3600*24*30);
// state is now 2
$_SESSION[«authstate»] = 2;
// redirect user to clear leftover GET variables
header(«Location: ‘ . $this->tmhOAuth->php_self());
exit;
}
|
Переадресация в конце предназначена для очистки параметров URL, оставленных Twitter, и позволяет cookie-файлам вступать в силу.
Шаг 3: Проверьте токен доступа
Получив наш токен доступа, мы должны убедиться, что он действителен. Вот метод, чтобы сделать это:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
/**
* Verify the validity of our access token
*
* @return bool Access token verified
*/
private function verifyAccessToken() {
$this->tmhOAuth->config[«user_token»] = $_COOKIE[«access_token»];
$this->tmhOAuth->config[«user_secret»] = $_COOKIE[«access_token_secret»];
// send verification request to test access key
$this->tmhOAuth->request(«GET», $this->tmhOAuth->url(«1/account/verify_credentials»));
// store the user data returned from the API
$this->userdata = json_decode($this->tmhOAuth->response[«response»]);
// HTTP 200 means we were successful
return ($this->tmhOAuth->response[«code»] == 200);
}
|
Этот код должен выглядеть довольно знакомым к настоящему времени. Все, что мы здесь делаем, это устанавливаем user_token
и user_secret
и делаем запрос GET равным 1 / account / verify_credentials . Если Twitter отвечает кодом 200, то токен доступа действителен.
Еще одна деталь, на которую стоит обратить внимание, — это то, где мы заполняем свойство $userdata
данными, возвращаемыми этим запросом Twitter. Данные представлены в формате JSON, поэтому мы используем json_decode()
для преобразования их в объект PHP. Вот эта строка снова:
1
2
|
// store the user data returned from the API
$this->userdata = json_decode($this->tmhOAuth->response[«response»]);
|
Шаг 4: связать все вместе
С нашими компонентами OAuth пришло время связать все вместе. Нам нужен общедоступный метод, позволяющий нашему клиентскому коду запустить процесс аутентификации, и вот он:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* Authenticate user with Twitter
*
* @return bool Authentication successful
*/
public function auth() {
// state 1 requires a GET variable to exist
if($this->state == 1 && !isset($_GET[«oauth_verifier»])) {
$this->state = 0;
}
// Step 1: Get a request token
if($this->state == 0) {
return $this->getRequestToken();
}
// Step 2: Get an access token
elseif($this->state == 1) {
return $this->getAccessToken();
}
// Step 3: Verify the access token
return $this->verifyAccessToken();
}
|
Большая часть метода auth()
не требует пояснений. Основываясь на состоянии, он выполняет соответствующий метод для этой стадии аутентификации. Если состояние равно 1, должна существовать переменная GET oauth_verifier
, поэтому метод также проверяет это.
Теперь мы должны создать публичный метод, чтобы узнать, аутентифицированы ли мы. Этот isAuthed()
возвращает true, если состояние равно 2:
1
2
3
4
5
6
7
8
|
/**
* Check the current state of authentication
*
* @return bool True if state is 2 (authenticated)
*/
public function isAuthed() {
return $this->state == 2;
}
|
Мы также можем использовать метод для удаления аутентификации пользователя. Этот endSession()
устанавливает состояние в 0 и удаляет куки, содержащие токен доступа:
1
2
3
4
5
6
7
8
9
|
/**
* Remove user’s access token cookies
*/
public function endSession() {
$this->state = 0;
$_SESSION[«authstate»] = 0;
setcookie(«access_token», «», 0);
setcookie(«access_token_secret», «», 0);
}
|
инициализация
Теперь нам нужно добавить некоторые вещи в наш __construct()
чтобы выяснить, в каком состоянии аутентификации находится приложение при инициализации. Кроме того, поскольку наш код использует переменные сеанса, мы должны убедиться, что сеанс запущен с этим кодом:
1
2
3
4
|
// start a session if one does not exist
if(!session_id()) {
session_start();
}
|
Эта следующая часть, где мы определяем состояние. Состояние начинается с 0; если существуют файлы cookie, содержащие токен доступа, состояние считается равным 2; в противном случае состояние устанавливается authstate
переменной сеанса authstate
если она существует. Вот код:
01
02
03
04
05
06
07
08
09
10
11
|
// determine the authentication status
// default to 0
$this->state = 0;
// 2 (authenticated) if the cookies are set
if(isset($_COOKIE[«access_token»], $_COOKIE[«access_token_secret»])) {
$this->state = 2;
}
// otherwise use value stored in session
elseif(isset($_SESSION[«authstate»])) {
$this->state = (int)$_SESSION[«authstate»];
}
|
Если состояние 1, это означает, что мы находимся в процессе аутентификации. Таким образом, мы можем продолжить и продолжить процесс на этом этапе:
1
2
3
4
|
// if we are in the process of authentication we continue
if($this->state == 1) {
$this->auth();
}
|
Если состояние 2, мы должны проверить токен доступа. Если аутентификация не удалась, этот код очищает куки и сбрасывает состояние:
1
2
3
4
|
// verify authentication, clearing cookies if it fails
elseif($this->state == 2 && !$this->auth()) {
$this->endSession();
}
|
Вот новый конструктор с этими изменениями:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
/**
* Initialize a new TwitterApp object
*
* @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
*/
public function __construct(tmhOAuth $tmhOAuth) {
// save the tmhOAuth object
$this->tmhOAuth = $tmhOAuth;
// start a session if one does not exist
if(!session_id()) {
session_start();
}
// determine the authentication status
// default to 0
$this->state = 0;
// 2 (authenticated) if the cookies are set
if(isset($_COOKIE[«access_token»], $_COOKIE[«access_token_secret»])) {
$this->state = 2;
}
// otherwise use value stored in session
elseif(isset($_SESSION[«authstate»])) {
$this->state = (int)$_SESSION[«authstate»];
}
// if we are in the process of authentication we continue
if($this->state == 1) {
$this->auth();
}
// verify authentication, clearing cookies if it fails
elseif($this->state == 2 && !$this->auth()) {
$this->endSession();
}
}
|
Отправка твита
Теперь, когда весь код авторизации завершен, мы можем добавить некоторые общие функции в наш класс. Вот метод отправки твита через Twitter API:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
/**
* Send a tweet on the user’s behalf
*
* @param string $text Text to tweet
* @return bool Tweet successfully sent
*/
public function sendTweet($text) {
// limit the string to 140 characters
$text = substr($text, 0, 140);
// POST the text to the statuses/update method
$this->tmhOAuth->request(«POST», $this->tmhOAuth->url(«1/statuses/update»), array(
‘status’ => $text
));
return ($this->tmhOAuth->response[«code»] == 200);
}
|
Метод sendTweet()
принимает строку, ограничивает ее 140 символами, а затем отправляет в запросе POST значение 1 / statuses / update . Этот шаблон должен быть довольно знакомым к настоящему времени.
Полный класс TwitterApp
<? PHP класс TwitterApp { / ** * Эта переменная содержит объект tmhOAuth, используемый в классе * * @var tmhOAuth Объект класса tmhOAuth * / public $ tmhOAuth; / ** * Данные учетной записи пользователя Twitter * * @var array Информация о текущем аутентифицированном пользователе * / public $ userdata; / ** * Состояние аутентификации * * Ценности: * - 0: не авторизован * - 1: запрос токена получен * - 2: получен токен доступа (авторизован) * * @var int Текущее состояние аутентификации * / защищенное состояние $; / ** * Инициализировать новый объект TwitterApp * * @param tmhOAuth $ tmhOAuth Объект tmhOAuth с ключом потребителя и секретом * / публичная функция __construct (tmhOAuth $ tmhOAuth) { // сохранить объект tmhOAuth $ this-> tmhOAuth = $ tmhOAuth; // начать сеанс, если он не существует if (! session_id ()) { session_start (); } // определить статус аутентификации // по умолчанию 0 $ this-> state = 0; // 2 (аутентифицировано), если куки установлены if (isset ($ _ COOKIE ["access_token"], $ _COOKIE ["access_token_secret"])) { $ this-> state = 2; } // иначе используем значение, сохраненное в сеансе elseif (isset ($ _ SESSION ["authstate"])) { $ this-> state = (int) $ _ SESSION ["authstate"]; } // если мы находимся в процессе аутентификации, мы продолжаем if ($ this-> state == 1) { $ This-> Auth (); } // проверка подлинности, очистка куки в случае неудачи elseif ($ this-> state == 2 &&! $ this-> auth ()) { $ This-> endSession (); } } / ** * Аутентифицировать пользователя с помощью Twitter * * @return bool Аутентификация прошла успешно * / публичная функция auth () { // состояние 1 требует наличия переменной GET if ($ this-> state == 1 &&! isset ($ _ GET ["oauth_verifier"])) { $ this-> state = 0; } // Шаг 1: Получить токен запроса if ($ this-> state == 0) { return $ this-> getRequestToken (); } // Шаг 2: Получить токен доступа elseif ($ this-> state == 1) { return $ this-> getAccessToken (); } // Шаг 3: проверка токена доступа return $ this-> verifyAccessToken (); } / ** * Получить токен запроса из Twitter * * @return bool False, если запрос не выполнен * / приватная функция getRequestToken () { // отправить запрос на токен запроса $ this-> tmhOAuth-> request ("POST", $ this-> tmhOAuth-> url ("oauth / request_token", ""), массив ( // передать переменную для установки обратного вызова 'oauth_callback' => $ this-> tmhOAuth-> php_self () )); if ($ this-> tmhOAuth-> response ["code"] == 200) { // получить и сохранить токен запроса $ response = $ this-> tmhOAuth-> extract_params ($ this-> tmhOAuth-> response ["response"]); $ _SESSION ["authtoken"] = $ response ["oauth_token"]; $ _SESSION ["authsecret"] = $ response ["oauth_token_secret"]; // состояние теперь 1 $ _SESSION ["authstate"] = 1; // перенаправить пользователя в Twitter для авторизации $ url = $ this-> tmhOAuth-> url ("oauth / authorize", ""). '? oauth_token ='. $ Ответ [ "oauth_token"]; header ("Местоположение: '. $ url); выход; } вернуть ложь; } / ** * Получить токен доступа из Twitter * * @return bool False, если запрос не выполнен * / приватная функция getAccessToken () { // установить токен запроса и секрет, который мы сохранили $ this-> tmhOAuth-> config ["user_token"] = $ _SESSION ["authtoken"]; $ this-> tmhOAuth-> config ["user_secret"] = $ _SESSION ["authsecret"]; // отправить запрос на токен доступа $ this-> tmhOAuth-> request ("POST", $ this-> tmhOAuth-> url ("oauth / access_token", ""), массив ( // передать полученный из твиттера oauth_verifier 'oauth_verifier' => $ _GET ["oauth_verifier"] )); if ($ this-> tmhOAuth-> response ["code"] == 200) { // получить токен доступа и сохранить его в куки $ response = $ this-> tmhOAuth-> extract_params ($ this-> tmhOAuth-> response ["response"]); setcookie ("access_token", $ response ["oauth_token"], time () + 3600 * 24 * 30); setcookie ("access_token_secret", $ response ["oauth_token_secret"], time () + 3600 * 24 * 30); // состояние теперь 2 $ _SESSION ["authstate"] = 2; // перенаправить пользователя на очистку оставшихся переменных GET header ("Местоположение: '. $ this-> tmhOAuth-> php_self ()); выход; } вернуть ложь; } / ** * Проверьте правильность нашего токена доступа * * @return bool Проверен токен доступа * / приватная функция verifyAccessToken () { $ this-> tmhOAuth-> config ["user_token"] = $ _COOKIE ["access_token"]; $ this-> tmhOAuth-> config ["user_secret"] = $ _COOKIE ["access_token_secret"]; // отправить запрос на проверку ключа доступа $ this-> tmhOAuth-> request ("GET", $ this-> tmhOAuth-> url ("1 / account / verify_credentials")); // сохраняем пользовательские данные, возвращенные из API $ this-> userdata = json_decode ($ this-> tmhOAuth-> response ["response"]); // HTTP 200 означает, что мы были успешны return ($ this-> tmhOAuth-> response ["code"] == 200); } / ** * Проверьте текущее состояние аутентификации * * @return bool Истинно, если состояние 2 (аутентифицировано) * / публичная функция isAuthed () { вернуть $ this-> state == 2; } / ** * Удалить пользовательский токен куки * / публичная функция endSession () { $ this-> state = 0; $ _SESSION ["authstate"] = 0; setcookie ("access_token", "", 0); setcookie ("access_token_secret", "", 0); } / ** * Отправить твит от имени пользователя * * @param string $ text Текст для твита * @return bool Твит успешно отправлен * / публичная функция sendTweet ($ text) { // ограничиваем строку до 140 символов $ text = substr ($ text, 0, 140); // POST текст к статусам / метод обновления $ this-> tmhOAuth-> request ("POST", $ this-> tmhOAuth-> url ("1 / statuses / update"), массив ( 'status' => $ text )); return ($ this-> tmhOAuth-> response ["code"] == 200); } }
Наше приложение
Теперь, когда у нас есть класс, который обрабатывает все задачи OAuth, мы можем теперь расширить его с помощью функций, специфичных для нашего приложения. Это включает в себя возможность получить, изменить и установить аватар пользователя.
Мы будем расширять класс TwitterApp классом TwitterAvatars. Начните со следующего кода в новом файле с именем lib/TwitterAvatars.php
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<?php
class TwitterAvatars extends TwitterApp {
/**
* The path to our temporary files directory
*
* @var string Path to store image files
*/
public $path;
/**
* These are all the GD image filters available in this class
*
* @var array Associative array of image filters
*/
protected $filters = array(
‘grayscale’ => IMG_FILTER_GRAYSCALE,
‘negative’ => IMG_FILTER_NEGATE,
‘edgedetect’ => IMG_FILTER_EDGEDETECT,
’embossed’ => IMG_FILTER_EMBOSS,
‘blurry’ => IMG_FILTER_GAUSSIAN_BLUR,
‘sketchy’ => IMG_FILTER_MEAN_REMOVAL
);
/**
* Initialize a new TwitterAvatars object
*
* @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
* @param string $path Path to store image files (default ‘tmp»)
*/
public function __construct(tmhOAuth $tmhOAuth, $path = ‘tmp») {
// call the parent class’ constructor
parent::__construct($tmhOAuth);
// save the path variable
$this->path = $path;
}
}
|
Как вы можете видеть, расширенный класс включает в себя свойство $path
указывающее, куда будут перемещаться временные файлы изображений, свойство $filters
содержащее массив фильтров изображений, и расширенный конструктор с параметром для установки пути. Поскольку мы переопределяем исходный конструктор, мы должны явно вызвать конструктор parent::__construct()
с помощью parent::__construct()
.
Теперь мы можем начать добавлять наши методы.
загрузка
Очевидно, нам понадобится возможность загружать изображения, чтобы манипулировать ими. Вот общий метод download()
который принимает URL и возвращает данные в этом месте. Метод делает основной запрос cURL.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
/**
* Download data from specified URL
*
* @param string $url URL to download
* @return string Downloaded data
*/
protected function download($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
|
Поиск URL
Теперь, когда мы можем загружать файлы, нам нужно найти расположение файлов, которые нам нужны. Нас интересуют два разных изображения: миниатюра стандартного размера и оригинальное полноразмерное изображение. Итак, мы создадим метод для получения каждого URL.
Чтобы получить миниатюру стандартного размера, мы вызовем метод API users / profile_image /: screen_name, который отвечает перенаправлением 302 на изображение аватара указанного пользователя. Это означает, что URL будет найден в заголовке Location. Вот этот метод:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/**
* Get the URL to the standard sized avatar
*
* @return string The URL to the image file
*/
protected function getImageURL() {
// request user’s ‘bigger’ profile image
$this->tmhOAuth->request(«GET», $this->tmhOAuth->url(«1/users/profile_image/» . $this->userdata->screen_name), array(
‘screen_name’ => $this->userdata->screen_name,
‘size’ => ‘bigger’
));
if($this->tmhOAuth->response[«code»] == 302) {
// the direct URL is in the Location header
return $this->tmhOAuth->response[«headers»][«location»];
}
throw new Exception(«Error locating image»);
}
|
Обратите внимание, что мы делаем запрос GET с помощью tmhOAuth, передавая параметры screen_name
и size
, а затем возвращая содержимое заголовка Location.
Нет метода API для получения полноразмерного изображения, поэтому для нашего следующего метода мы немного обманем и отредактируем URL. Пользовательские данные содержат поле profile_image_url , которое указывает на что-то вроде avatar_normal.jpg , а оригинальное изображение можно найти на avatar.jpg без суффикса. Таким образом, этот метод получает URL, удаляет суффикс размера и возвращает измененный URL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
/**
* Get the URL to the full sized avatar
*
* @return string The URL to the image file
*/
protected function getOriginalImageURL() {
// get the regular sized avatar
$url = $this->userdata->profile_image_url;
// save the extension for later
$ext = strrchr($url, ‘.»);
// strip the «_normal’ suffix and add back the extension
return substr($url, 0, strrpos($url, «_»)) .
}
|
Чтение изображений
Теперь, когда мы можем найти и загрузить изображения, нам нужен способ их чтения. Мы будем использовать библиотеку GD для управления изображениями, поэтому этот метод преобразует необработанные данные изображения в ресурс изображения GD.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/**
* Convert raw image data to a GD resource
*
* @param string $data Binary image data to parse
* @return resource A GD image resource identifier
*/
protected function readImage($data) {
// read in the original image
$src = imagecreatefromstring($data);
if(!$src) {
throw new Exception(«Error reading image»);
}
// get the dimensions
$width = imagesx($src);
$height = imagesy($src);
// create a blank true color image of the same size
$img = imagecreatetruecolor($width, $height);
// copy the original image to this new canvas
imagecopy($img, $src, 0, 0, 0, 0, $width, $height);
// discard the source image
imagedestroy($src);
return $img;
}
|
Чтобы описать, что происходит выше:
- Данные изображения преобразуются в ресурс GD с помощью функции
imagecreatefromstring ()
. - Размеры изображения записываются с использованием
imagesx ()
иimagesy ()
. - Новое пустое изображение истинного цвета с
imagecreatetruecolor ()
же размерами создается с помощьюimagecreatetruecolor ()
. - Исходное изображение копируется в новое изображение с помощью функции
imagecopy ()
. В результате получается оригинальная цветная версия исходного изображения независимо от исходного цветового режима. - Исходный ресурс изображения уничтожается с помощью
imagedestroy ()
и возвращается дескриптор нового изображения.
Сохранение изображений
Теперь, когда мы можем загружать изображения и создавать ресурс GD, нам нужен метод для сохранения изображений в файловой системе. Вот метод, который сохраняет предоставленное изображение как файл PNG с указанным именем, используя imagepng ()
:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/**
* Save a GD image resource to a PNG file
*
* @param resource $img GD image resource identifier
* @param string $name Name of the image
* @return string Path to the saved image
*/
protected function saveImage($img, $name) {
$path = $this->path .
imagepng($img, $path);
imagedestroy($img);
return $path;
}
|
Генерация превью
Теперь, когда у нас есть все части, которые приводят в действие наше приложение, мы можем начать собирать их вместе. В нашем потоке приложений мы предоставим пользователю возможность выбора из предварительного просмотра. Вот метод для создания этих превью:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
* Generate previews for each image filter
*
* @return array Associative array of image previews
*/
public function generatePreviews() {
// we need valid user info to know whose avatar to handle
if(!$this->isAuthed()) {
throw new Exception(«Requires oauth authorization»);
}
$username = $this->userdata->screen_name;
// cache the raw data to use
$data = $this->download($this->getImageURL());
// copy the original image
$img = $this->readImage($data);
$this->saveImage($img, $username . «_orig»);
// array to hold the list of previews
$images = array();
// loop through each filter to generate previews
foreach($this->filters as $filter_name => $filter) {
$img = $this->readImage($data);
imagefilter($img, $filter);
$images[$filter_name] = $this->saveImage($img, $username . «_’ . $filter_name);
}
return $images;
}
|
Первое, что мы делаем, это проверяем, что пользователь прошел проверку подлинности, а затем подбираем имя пользователя для использования в именах файлов.
1
2
3
4
5
|
// we need valid user info to know whose avatar to handle
if(!$this->isAuthed()) {
throw new Exception(«Requires oauth authorization»);
}
$username = $this->userdata->screen_name;
|
Затем мы загружаем изображение пользователя, используя методы getImageURL()
и download()
которые мы создали. Эти данные будут неоднократно использоваться для каждого предварительного просмотра, поэтому мы сохраняем их в переменной $data
.
1
2
|
// cache the raw data to use
$data = $this->download($this->getImageURL());
|
Далее мы сохраняем неизмененную копию с суффиксом _orig. Это для визуального сравнения позже.
1
2
3
|
// copy the original image
$img = $this->readImage($data);
$this->saveImage($img, $username . «_orig»);
|
В последней части метода мы перебираем фильтры изображений, перечисленные в свойстве $filters
, создавая изображение для каждого фильтра. На каждой итерации мы создаем изображение и применяем imagefilter ()
, которая принимает одну из констант, перечисленных в массиве $filters
. Затем для каждого сохраняемого изображения мы добавляем его путь к ассоциативному массиву (используя имя фильтра в качестве ключа), который этот метод возвращает в конце.
01
02
03
04
05
06
07
08
09
10
11
|
// array to hold the list of previews
$images = array();
// loop through each filter to generate previews
foreach($this->filters as $filter_name => $filter) {
$img = $this->readImage($data);
imagefilter($img, $filter);
$images[$filter_name] = $this->saveImage($img, $username . «_’ . $filter_name);
}
return $images;
|
Следующая часть нашего потока приложений просит пользователя подтвердить свой выбор, поэтому нам нужен способ найти конкретный предварительный просмотр. Вот простой способ получить путь к изображению на основе параметра, переданного в качестве параметра, по умолчанию к исходному изображению:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
/**
* Get the path to a previously generated preview
*
* @param string $filter The image filter to get the preview for
* @return string The path to the preview file or null if not found
*/
public function getPreview($filter = ‘orig») {
if(!$this->isAuthed()) {
throw new Exception(«Requires oauth authorization»);
}
$path = $this->path .
if(file_exists($path)) {
return $path;
}
return null;
}
|
Изменение аватара
Завершающим этапом нашего потока приложений является фактическое изменение аватара пользователя. Сначала нам нужен метод, чтобы получить полноразмерное изображение и применить к нему определенный фильтр. Вот:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/**
* Process the user’s full avatar using one of the filters
*
* @param string $filter The filter to apply to the image
* @return string Path to the output file
*/
protected function processImage($filter = «grayscale») {
// make sure the filter exists
$filter = strtolower($filter);
if(!array_key_exists($filter, $this->filters)) {
throw new Exception(«Unsupported image filter»);
}
$username = $this->userdata->screen_name;
// get the full sized avatar
$data = $this->download($this->getOriginalImageURL());
$img = $this->readImage($data);
// apply the filter to the image
imagefilter($img, $this->filters[$filter]);
// save the image and return the path
return $this->saveImage($img, $username . «_’ . $filter . «_full»);
}
|
Это должно быть легко понять, поскольку оно очень похоже на метод generatePreviews()
. Он принимает параметр для указания фильтра изображения и проверяет его наличие. Затем он загружает исходное изображение и применяет к нему фильтр, возвращая путь к сгенерированному изображению в качестве возвращаемого значения.
Теперь нам нужен метод, который фактически отправляет сгенерированное изображение в Twitter, обновляя аватар пользователя. Этот метод вызывает метод processImage()
для создания изображения и загружает его в Twitter с помощью метода API 1 / account / update_profile_image :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/**
* Update user’s avatar with a filtered version
*
* @param string $filter The filter to use
* @return bool Operation successful
*/
public function commitAvatar( $filter ) { if (! $this ->isAuthed()) { throw new Exception( "Requires oauth authorization" ); }
// generate the image and get the path $path = $this ->processImage( $filter ); if ( file_exists ( $path )) { // send a multipart POST request with the image file data $this ->tmhOAuth->request( "POST" , $this ->tmhOAuth->url( "1/account/update_profile_image" ), array ( // format: @local/path.png;type=mime/type;filename=file_name.png 'image' => '@' . $path . ';type=image/png;filename=' . basename ( $path ) ), true, true); return ( $this ->tmhOAuth->response[ "code" ] == 200); }
return false;
}
|
Сложной частью здесь является фактический POST-запрос tmhOAuth, который представляет собой многоэлементный запрос, содержащий необработанные данные изображения. Для этого мы должны установить последний параметр tmhOAuth::request()
метода true
и передать image
переменную в специальном формате:
@ [ path_to_image ]; type = [ mime_type ]; filename = [ file_name ]
Например, если мы хотим загрузить tmp / username_grayscale_full.png, значение будет равно @tmp/username_grayscale_full.png;type=image/png;filename=username_grayscale_full.png
.
Вот снова эта часть кода:
1
2
3
4
5
|
// send a multipart POST request with the image file data $this ->tmhOAuth->request( "POST" , $this ->tmhOAuth->url( "1/account/update_profile_image" ), array ( // format: @local/path.png;type=mime/type;filename=file_name.png 'image' => '@' . $path . ';type=image/png;filename=' . basename ( $path ) ), true, true); |
Убираться
Побочным эффектом всех этих манипуляций с файлами является то, что многие временные файлы остаются позади. Вот метод для очистки временного каталога:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
* Delete leftover image files */
public function cleanupFiles() { // file to track when we last checked $flag = $this ->path . "/.last_check'; $time = time(); // have we checked within the last hour? if (! file_exists ( $flag ) || $time - filemtime ( $flag ) > 3600) { // get an array of PNG files in the directory $files = glob ( $this ->path . "/*.png" ); // loop through files, deleting old files (12+ hours) foreach($files as $file) {
if ( $time - filemtime ( $file ) > 60*60*12) { unlink( $file ); }
}
// update the timestamp of our flag file touch( $flag ); }
}
|
Это просто перебирает файлы PNG, удаляя те, которым больше 12 часов. Он также проверяет, сколько времени прошло с тех пор, как мы проверили, используя отметку времени в файле .last_check, что позволяет нам ограничить проверку до одного в час. Таким образом, мы можем вызывать этот метод при каждом запросе, не тратя ресурсы.
Примечание: мы используем glob()
функцию в PHP, которая является простым способом получить массив файлов, соответствующих шаблону.
Полный класс TwitterAvatars
&? PHP класс TwitterAvatars расширяет TwitterApp { / ** * Путь к нашему каталогу временных файлов * * @var строка Путь для хранения файлов изображений * / public $ path; / ** * Это все фильтры изображений GD, доступные в этом классе * * @var array Ассоциативный массив фильтров изображений * / Защищенные $ filters = array ( 'grayscale' => IMG_FILTER_GRAYSCALE, 'негативный' => IMG_FILTER_NEGATE, 'edgedetect' => IMG_FILTER_EDGEDETECT, 'выбито' => IMG_FILTER_EMBOSS, 'blurry' => IMG_FILTER_GAUSSIAN_BLUR, 'sketchy' => IMG_FILTER_MEAN_REMOVAL ); / ** * Инициализировать новый объект TwitterAvatars * * @param tmhOAuth $ tmhOAuth Объект tmhOAuth с ключом потребителя и секретом * @param string $ path Путь для хранения файлов изображений (по умолчанию «tmp») * / публичная функция __construct (tmhOAuth $ tmhOAuth, $ path = 'tmp ") { // вызываем конструктор родительского класса Родитель :: __ конструкт ($ tmhOAuth); // сохранить переменную пути $ this-> path = $ path; } / ** * Скачать данные с указанного URL * * @param string $ url URL для загрузки * @return string Загруженные данные * / загрузка защищенной функции ($ url) { $ ch = curl_init (); curl_setopt ($ ch, CURLOPT_URL, $ url); curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, true); $ ret = curl_exec ($ ch); curl_close ($ ч); вернуть $ ret; } / ** * Получить URL для аватара стандартного размера * * @return string URL к файлу изображения * / защищенная функция getImageURL () { // запросим изображение пользователя большего размера $ this-> tmhOAuth-> request ("GET", $ this-> tmhOAuth-> url ("1 / users / profile_image / '. $ this-> userdata-> screen_name), массив ( 'screen_name' => $ this-> userdata-> screen_name, «размер» => «больше» )); if ($ this-> tmhOAuth-> response ["code"] == 302) { // прямой URL находится в заголовке Location return $ this-> tmhOAuth-> response ["headers"] ["location"]; } выдать новое исключение («Ошибка при поиске изображения»); } / ** * Получить URL для полноразмерного аватара * * @return string URL к файлу изображения * / защищенная функция getOriginalImageURL () { // получить аватар обычного размера $ url = $ this-> userdata-> profile_image_url; // сохранить расширение на потом $ ext = strrchr ($ url, '. "); // удаляем суффикс "_normal" и добавляем расширение вернуть substr ($ url, 0, strrpos ($ url, "_")). $ Вен; } / ** * Преобразование необработанных данных изображения в ресурс GD * * @param string $ data Двоичные данные изображения для анализа * @return resource Идентификатор ресурса изображения GD * / защищенная функция readImage ($ data) { // читаем в исходном изображении $ src = imagecreatefromstring ($ data); if (! $ src) { выдать новое исключение («Ошибка чтения изображения»); } // получаем размеры $ width = imagesx ($ src); $ height = imagesy ($ src); // создаем пустое изображение истинного цвета того же размера $ img = imagecreatetruecolor ($ width, $ height); // копируем оригинальное изображение на этот новый холст imagecopy ($ img, $ src, 0, 0, 0, 0, $ width, $ height); // сбросить исходное изображение ImageDestroy ($ ЦСИ); вернуть $ img; } / ** * Сохранить ресурс изображения GD в файл PNG * * @param resource $ img Идентификатор ресурса изображения GD * @param string $ name Название изображения * @return string Путь к сохраненному изображению * / защищенная функция saveImage ($ img, $ name) { $ path = $ this-> path. "/ '. $ name.' .png '; imagepng ($ img, $ path); ImageDestroy ($ IMG); вернуть $ путь; } / ** * Генерация превью для каждого фильтра изображения * * @return array Ассоциативный массив превью изображений * / публичная функция generatePreviews () { // нам нужна действительная информация о пользователе, чтобы знать, чей аватар обрабатывать if (! $ this-> isAuthed ()) { выдать новое исключение («Требуется авторизация oauth»); } $ username = $ this-> userdata-> screen_name; // кэшируем необработанные данные для использования $ data = $ this-> download ($ this-> getImageURL ()); // копируем оригинальное изображение $ img = $ this-> readImage ($ data); $ this-> saveImage ($ img, $ username. "_orig"); // массив для хранения списка превью $ images = array (); // цикл через каждый фильтр для генерации предварительного просмотра foreach ($ this-> фильтрует как $ filter_name => $ filter) { $ img = $ this-> readImage ($ data); imagefilter ($ img, $ filter); $ images [$ filter_name] = $ this-> saveImage ($ img, $ username. "_ '. $ filter_name); } вернуть $ изображения; } / ** * Получить путь к ранее созданному предварительному просмотру * * @param string $ filter Фильтр изображения для предварительного просмотра * @return string Путь к файлу предварительного просмотра или ноль, если не найден * / публичная функция getPreview ($ filter = 'orig ") { if (! $ this-> isAuthed ()) { выдать новое исключение («Требуется авторизация oauth»); } $ path = $ this-> path. "/ '. $ this-> userdata-> screen_name." _'. $ фильтр. '.Png'; if (file_exists ($ path)) { вернуть $ путь; } вернуть ноль; } / ** * Обработать полный аватар пользователя, используя один из фильтров * * @param string $ filter Фильтр для применения к изображению * @return string Путь к выходному файлу * / защищенная функция processImage ($ filter = 'grayscale ") { // убедитесь, что фильтр существует $ filter = strtolower ($ filter); if (! array_key_exists ($ filter, $ this-> filters)) { выдать новое исключение («Неподдерживаемый фильтр изображений»); } $ username = $ this-> userdata-> screen_name; // получить полноразмерный аватар $ data = $ this-> download ($ this-> getOriginalImageURL ()); $ img = $ this-> readImage ($ data); // применяем фильтр к изображению imagefilter ($ img, $ this-> filters [$ filter]); // сохранить изображение и вернуть путь return $ this-> saveImage ($ img, $ username. "_ '. $ filter." _full "); } / ** * Обновить аватар пользователя отфильтрованной версией * * @param string $ filter Фильтр для использования * @return bool Операция прошла успешно * / публичная функция commitAvatar ($ filter) { if (! $ this-> isAuthed ()) { выдать новое исключение («Требуется авторизация oauth»); } // генерируем изображение и получаем путь $ path = $ this-> processImage ($ filter); if (file_exists ($ path)) { // отправляем многочастный POST-запрос с данными файла изображения $ this-> tmhOAuth-> request ("POST", $ this-> tmhOAuth-> url ("1 / account / update_profile_image"), массив ( // формат: @ local / path.png; type = mime / type; filename = file_name.png 'image' => '@'. $ path. '; type = image / png; filename ='. базовый ($ путь) ), правда правда); return ($ this-> tmhOAuth-> response ["code"] == 200); } вернуть ложь; } / ** * Удалить оставшиеся файлы изображений * / public function cleanupFiles () { // файл для отслеживания, когда мы последний раз проверяли $ flag = $ this-> path. "/.Последняя проверка'; $ time = time (); // мы проверили в течение последнего часа? if (! file_exists ($ flag) || $ time - filemtime ($ flag)> 3600) { // получить массив файлов PNG в каталоге $ files = glob ($ this-> path. "/*.png"); // цикл по файлам, удаление старых файлов (более 12 часов) foreach ($ files as $ file) { if ($ time - filemtime ($ file)> 60 * 60 * 12) { Разорвать связь ($ файла); } } // обновляем временную метку нашего файла флага потрогать ($ флаг); } } }
Передний конец
У нас есть все компоненты приложения вместе, так что теперь все, что нам нужно, это пользовательский интерфейс. Весь код будет помещен в файл index.php в корневом каталоге. Начнем с включения библиотек и установки конфигурации:
01
02
03
04
05
06
07
08
09
10
11
|
<?php
// include our libraries include 'lib/tmhOAuth.php' ; include 'lib/TwitterApp.php' ; include 'lib/TwitterAvatars.php' ; // set the consumer key and secret define( "CONSUMER_KEY" , 'qSkJum23MqlG6greF8Z76A"); define( "CONSUMER_SECRET" , 'Bs738r5UY2R7e5mwp1ilU0voe8OtXAtifgtZe9EhXw"); ?>
|
Примечание: обязательно замените CONSUMER_KEY
и CONSUMER_SECRET
на свой.
Мы собираемся поместить наш код в блок try-catch, чтобы мы могли корректно обрабатывать любые ошибки, присваивая их сообщения $error
переменной.
1
2
3
4
5
6
7
|
try {
} catch(Exception $e) {
// catch any errors that may occur $error = $e ; }
|
Внутри блока try мы можем начать писать наш код, начиная с инициализации объекта TwitterAvatars, вызываемого $ta
с помощью настроенного объекта tmhOAuth:
1
2
3
4
5
6
7
8
|
// our tmhOAuth settings $config = array(
'consumer_key' => CONSUMER_KEY, 'consumer_secret' => CONSUMER_SECRET );
// create a new TwitterAvatars object $ta = new TwitterAvatars( new tmhOAuth( $config )); |
Мы можем удалить все старые временные файлы на этом этапе:
1
2
|
// check for stale files $ta ->cleanupFiles(); |
Затем мы проверяем, прошел ли пользователь аутентификацию или, если это не удалось, запросил ли пользователь аутентификацию, и в этом случае мы запускаем процесс, вызывая auth()
метод:
01
02
03
04
05
06
07
08
09
10
|
// check our authentication status if ( $ta ->isAuthed()) { }
// did the user request authorization? elseif (isset( $_POST [ "auth" ])) { // start authentication process $ta ->auth(); }
|
Если пользователь аутентифицирован, нам нужно проверить, была ли выбрана опция, в противном случае мы будем генерировать превью:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
// check our authentication status if ( $ta ->isAuthed()) { // has the user selected an option? if (isset( $_POST [ "filter" ])) { }
// generate previews if the user has not chosen else {
// $previews will be a list of images $previews = $ta ->generatePreviews(); }
}
|
Если была выбрана опция, нам нужно получить пути к старым и новым изображениям для отображения:
1
2
3
4
5
6
7
|
// has the user selected an option? if (isset( $_POST [ "filter" ])) { // get the image paths for display $original = $ta ->getPreview(); $newimage = $ta ->getPreview( $_POST [ "filter" ]); }
|
Наконец, мы проверяем, подтвердил ли пользователь свой выбор, и применяем изменения. Мы также отправляем твит по запросу и устанавливаем $success
переменную в true
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
// has the user selected an option? if (isset( $_POST [ "filter" ])) { // is the user sure? if (isset( $_POST [ "confirm" ])) { // change the user's avatar $ta ->commitAvatar( $_POST [ "filter" ]); // tweet if the user chose to if (isset( $_POST [ "tweet" ])) { $ta ->sendTweet( "I just updated my avatar using Avatar Effects..." ); }
$success = true;
}
// get the image paths for display $original = $ta ->getPreview(); $newimage = $ta ->getPreview( $_POST [ "filter" ]); }
|
Вот что мы имеем до сих пор:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
<?php
// include our libraries include 'lib/tmhOAuth.php' ; include 'lib/TwitterApp.php' ; include 'lib/TwitterAvatars.php' ; // set the consumer key and secret define( "CONSUMER_KEY" , 'qSkJum23MqlG6greF8Z76A"); define( "CONSUMER_SECRET" , 'Bs738r5UY2R7e5mwp1ilU0voe8OtXAtifgtZe9EhXw"); try {
// our tmhOAuth settings $config = array(
'consumer_key' => CONSUMER_KEY, 'consumer_secret' => CONSUMER_SECRET );
// create a new TwitterAvatars object $ta = new TwitterAvatars( new tmhOAuth( $config )); // check for stale files $ta ->cleanupFiles(); // check our authentication status if ( $ta ->isAuthed()) { // has the user selected an option? if (isset( $_POST [ "filter" ])) { // is the user sure? if (isset( $_POST [ "confirm" ])) { // change the user's avatar $ta ->commitAvatar( $_POST [ "filter" ]); // tweet if the user chose to if (isset( $_POST [ "tweet" ])) { $ta ->sendTweet( "I just updated my avatar using Avatar Effects..." ); }
$success = true;
}
// get the image paths for display $original = $ta ->getPreview(); $newimage = $ta ->getPreview( $_POST [ "filter" ]); }
// generate previews if the user has not chosen else {
// $previews will be a list of images $previews = $ta ->generatePreviews(); }
}
// did the user request authorization? elseif (isset( $_POST [ "auth" ])) { // start authentication process $ta ->auth(); }
} catch(Exception $e) {
// catch any errors that may occur $error = $e ; }
?>
|
HTML
После кода PHP мы выведем соответствующий HTML, начиная с этого шаблона, который устанавливает заголовок и основной заголовок:
01
02
03
04
05
06
07
08
09
10
11
|
<!DOCTYPE html>
<html>
<head>
<meta charset=»UTF-8″>
< title >Twitter Avatar Effects</ title > <link rel=»stylesheet» href=»css/style.css»>
</head>
<body>
< h1 >Twitter Avatar Effects</ h1 > </body>
</html>
|
Вот где мы отображаем форму с входными данными для каждого предварительного просмотра:
01
02
03
04
05
06
07
08
09
10
11
|
<?php if (isset( $previews )): ?> <h2>Choose your weapon...</h2> <form action=»index.php» method=»post»>
<?php foreach ( $previews as $filter => $path ): ?> <input type= "image" src= "<?php echo $path; ?>" alt= "<?php echo ucfirst($filter); ?>" width= "73" height= "73" name= "filter" value= "<?php echo $filter; ?>" > <?php endforeach;
</form>
<p>Select one of the images above to change your Twitter avatar.</p> |
Вот страница успеха:
1
2
3
4
|
<?php elseif (isset( $success )): ?> <h2>Success! Your Twitter avatar is now:</h2> <img src= "<?php echo $newimage; ?>" alt= "Your Avatar" width= "73" height= "73" > |
Вот страница подтверждения, где мы показываем сравнение и предлагаем возможность отменить:
01
02
03
04
05
06
07
08
09
10
11
12
|
<?php elseif (isset( $newimage )): ?> <h2>Are you sure?</h2> <img src= "<?php echo $original; ?>" alt= "Original" width= "73" height= "73" > <span class = "arrow" >⇒</span> <img src= "<?php echo $newimage; ?>" alt= "<?php echo ucfirst($_POST[" filter "]); ?>" > <form action=»index.php» method=»post»>
<input type= "hidden" name= "filter" value= "<?php echo $_POST[" filter "]; ?>" > <input type= "submit" name= "confirm" value= "Confirm" > <a href= "index.php" >Cancel</a> <p><label>Tweet about your new avatar? <input type= "checkbox" name= "tweet" value= "true" ></label></p> </form>
|
Обратите внимание, что форма подтверждения содержит выбранный фильтр в скрытом поле.
Если есть ошибка, мы показываем это:
1
2
|
<?php elseif (isset( $error )): ?> <p>Error. <a href= "index.php" >Try again?</a></p> |
По умолчанию отображается кнопка «Подключиться к Twitter» в качестве входного изображения (загрузите одно из изображений внизу этой страницы в каталог img):
1
2
3
4
5
6
7
|
<?php else: ?>
<form action=»index.php» method=»post»>
<input type= "image" src= "img/sign-in-with-twitter-l.png" alt= "Connect to Twitter" name= "auth" value= "1" > </form>
<p>Connect to Twitter to use this app.</p> <?php endif;
|
Вот полный раздел HTML:
<! DOCTYPE html> <HTML> <Голова> <meta charset = "UTF-8"> <title> Эффекты аватара в Twitter </ title> <link rel = "stylesheet" href = "css / style.css"> </ HEAD> <Тело> <h1> Эффекты аватара в Twitter </ h1> <? php if (isset ($ previews)):?> <h2> Выбери свое оружие ... </ h2> <form action = "index.php" method = "post"> <? php foreach ($ previews как $ filter => $ path):?> <input type = "image" src = "<? php echo $ path;?>" alt = "<? php echo ucfirst ($ filter);?>" ширина = "73" высота = "73" name = "filter" value = "<? php echo $ filter;?>"> <? php endforeach; ?> </ Форма> <p> Выберите одно из изображений выше, чтобы изменить свой аватар в Twitter. </ p> <? php elseif (isset ($ success)):?> <H2> Успех! Ваш аватар в Твиттере сейчас: </ h2> <img src = "<? php echo $ newimage;?>" alt = "Ваш аватар" width = "73" height = "73"> <p> <a href="http://twitter.com/<?php echo $ta-> userdata-> screen_name;?> "> Посмотрите его </a> </ p> <? php elseif (isset ($ newimage)):?> <h2> Ты уверен? </ h2> <img src = "<? php echo $ original;?>" alt = "Original" width = "73" height = "73"> <span class = "arrow"> & rArr; </ span> <img src = "<? php echo $ newimage;?>" alt = "<? php echo ucfirst ($ _ POST [" filter "]);?>"> <form action = "index.php" method = "post"> <input type = "hidden" name = "filter" value = "<? php echo $ _POST [" filter "];?>"> <input type = "submit" name = "verify" value = "Confirm"> <a href="index.php"> Отмена </a> <p> <label> Чирикать о вашем новом аватаре? <input type = "checkbox" name = "tweet" value = "true"> </ label> </ p> </ Форма> <? php elseif (isset ($ error)):?> <Р> Ошибка. <a href="index.php"> Попробуйте еще раз? </a> </ p> <? php else:?> <form action = "index.php" method = "post"> <input type = "image" src = "img / sign-with-twitter-l.png" alt = "Подключиться к Twitter" name = "auth" value = "1"> </ Форма> <p> Подключитесь к Twitter, чтобы использовать это приложение. </ p> <? php endif; ?> </ Body> </ Html>
CSS
Вот некоторые основные CSS, чтобы интерфейс выглядел красиво, сохраненные в css / style.css :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
html {
background-color: #eee;
text-align: center;
font-family : "Lucida Grande" , Verdana , sans-serif ; font-size: 16px;
color : #224 ; }
body {
width: 700px;
margin: 30px auto;
background-color : #acf ; padding: 10px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
p {
font-size: 1em;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.6em;
}
.arrow {
font-size: 4em;
font-weight: bold;
}
|
Результаты
Вот видео, которое детализирует, как должно выглядеть наше заполненное приложение:
Вывод
Если вы полностью следовали этому руководству, у вас должно быть довольно хорошее понимание OAuth и того, что нужно для создания простого веб-приложения Twitter. Использовать Twitter API легко, если вы понимаете основные понятия, особенно если вы используете библиотеку, такую как tmhOAuth, для обработки мелких деталей.
Простой пример, который мы создали в этом уроке, может быть легко изменен или расширен для любых действий. Так что, если у вас есть отличная идея для нового крутого приложения Twitter, не стесняйтесь использовать его в качестве основы.
Спасибо за прочтение. Если у вас есть какие-либо вопросы или комментарии по поводу этого урока, пожалуйста, пишите!