だいぶ間が空いてしまいましたが、Twitter APIの申請(2020/2/11現在)の続きです。
申請した内容の通り、自分用の簡単な「いいね」管理のアプリを作成したのでメモしておきます。
……約半年かかってしまいました……。
簡易仕様
アプリの簡単な仕様は以下の通りになります。
- 自分のTwitterアカウントの「いいね」の一覧を取得し、表示する
- Twitter上のツイートへのリンクも付ける
- 各ツイートごと、または一覧表示されている全ての「いいね」に一括でチェックを付けて、「「いいね」を解除する」ボタンで選択したツイートの「いいね」を外す
- 処理完了後の画面で「いいね」を外したツイートの一覧を念のため再表示、ついでに
<textarea>
にMarkdownの箇条書き形式でツイートへのリンク一覧をダンプする
自分用なのでシンプルに。
動作サンプル
簡単な動作を図で示します。
1. ログイン
ログイン画面はログインボタンを付けたものを用意。
2. OAuthで認証
Twitterの認証画面に飛んで認証させます。
図は既にTwitterにログインしている状態でアクセスしたので「認証」ボタンだけですが、Twitterにログインしていない場合はアカウントIDとパスワードを求めるテキストボックスも付いてきますね。
3. トップページ
トップページは認証したユーザの「いいね」の一覧が表示されます。
図はサンプルとして猫の写真を適当に「いいね」しておいたものです。
4. 「いいね」解除
各ツイートの表示の下の方に「解除する」のチェックボックスがあります。これに1つずつチェックを付けて行くか、画面下端の「全ての「いいね」を解除リストに追加する」で一括でチェックを付けることで選択されます。
後は「選択した「いいね」を解除する」ボタンをクリックすれば、解除完了です。
5. 「いいね」解除完了
「いいね」解除完了すると上述の通り再表示とMarkdownの箇条書きでリンクがダンプされます。
実装上のポイント
実装上での躓いたポイントを記します。
1. 「いいね」解除はユーザ認証のみ( user context only
)
冒頭の通り「いいね」の解除を最終目標に据えていたのですが、該当ドキュメントでは
Requires authentication? Yes (user context only)
とありました。
この辺りに詳しく書かれていますが、
All write actions on the Twitter API require the user context.
とのことで、書き込みアクションは user context
、つまりユーザ認証が必要になるようです。アプリ単独認証だと読み取り専用までしかできないわけですね。
アプリ単独認証であれば、 Twitter API の利用申請の手順で発行した
- API key
- API secret key
それから、
- Access Token
- Access Secret
の4つで行けるのですが、ユーザ認証だと異なる手段が必要になります。
具体的には
- 登録した Twitter アプリで
Callback URL
を指定 - 実際に作成したアプリに以下のプログラムを用意する
login.php
: ログイン画面auth.php
: Twitter 認証画面へcallback.php
: コールバックを処理するプログラム(Callback URL
でアクセスされる)index.php
: アプリ画面(認証完了した実際の画面)
辺りが必要になるかと(1., 2.辺りは実装にも依りますが)。
以下、実際のコードから要点のみを抽出したサンプルプログラムを記します。
1.0. session.php
, config.php
: 共通処理(セッション周り、設定)
<?php
function requireLoginedSession()
{
// セッション開始
@session_start();
// ログインしていれば true を還す
if (isset($_SESSION['access_token'])) {
return true;
}
else {
return false;
}
}
function sessionDestroy()
{
setcookie(session_name(), '', 1);
session_destroy();
}
まず共通部分としてセッション管理をする部分を先に作っておきます。
<?php
define('CUSTOMER_KEY', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('CUSTOMER_SECRET', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('ACCESS_TOKEN', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('ACCESS_SECRET', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('CALLBACK', 'https://app.example.com/callback.php');
また、定数として諸々記述しておきます。
1.1. login.php
: ログイン画面
<?php
require_once './config.php';
require_once './session.php';
?>
<form method="post" action="./auth.php">
<button type="submit" class="btn btn-primary"><i class="fas fa-fw fa-sign-in-alt" aria-hidden="true"></i>ログイン</button>
</form>
ログイン画面はシンプルに2.の Twitter 認証画面へリクエストを投げるプログラムへPOSTするだけです。
1.2. auth.php
: Twitter 認証画面へ
<?php
require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';
use Abraham\TwitterOAuth\TwitterOAuth;
requireLoginedSession();
//TwitterOAuth のインスタンス化
$connection = new TwitterOAuth(
CUSTOMER_KEY,
CUSTOMER_SECRET
);
//コールバックをセット
$requestToken = $connection->oauth(
'oauth/request_token',
[
'oauth_callback' => CALLBACK
]
);
//コールバック用に $_SESSION に入れる
$_SESSION['oauth_token'] = $requestToken['oauth_token'];
$_SESSION['oauth_token_secret'] = $requestToken['oauth_token_secret'];
//Twitter 上の認証画面のURLを取得
$url = $connection->url(
'oauth/authenticate',
[
'oauth_token' => $requestToken['oauth_token']
]
);
//リダイレクト
header('Location: ' . $url);
続いて認証部分。 API key
( CUSTOMER_KEY
)と API secret key
( CUSTOMER_SECRET
)で TwitterOAuth
インスタンスを生成し、それを通じてアクセストークンを取得します。
1.3. callback.php
: コールバックを処理するプログラム( Callback URL
でアクセスされる)
<?php
require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';
use Abraham\TwitterOAuth\TwitterOAuth;
requireLoginedSession();
$requestToken = [
'oauth_token' => $_SESSION['oauth_token'],
'oauth_token_secret' => $_SESSION['oauth_token_secret']
];
if (
isset($_REQUEST['oauth_token'])
&& $requestToken['oauth_token'] === $_REQUEST['oauth_token']
&& isset($_REQUEST['oauth_verifier'])
) {
//成功時の処理
//Twitter からアクセストークンを取得する
$connection = new TwitterOAuth(
CUSTOMER_KEY,
CUSTOMER_SECRET,
$requestToken['oauth_token'],
$requestToken['oauth_token_secret']
);
$_SESSION['access_token'] = $connection->oauth(
'oauth/access_token',
[
'oauth_verifier' => $_REQUEST[self::OAUTH_VERIFIER_NAME]
]
);
//セッションIDをリジェネレート
session_regenerate_id();
//リダイレクト
header('Location: index.php');
}
else {
die('Error!');
}
続いて Twitter の認証画面から戻ってくるコールバック部分。
ちなみに、 Twitter の認証画面から戻ってくるとき、以下のようにGETパラメータが伴ってきます。
https://app.example.com/callback.php?oauth_token=AAAAAAAAAAAAAAAAAAAAAAAAAAA&oauth_verifier=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
この oauth_token
と oauth_verifier
を拾って処理をしています。
1.4. index.php
: アプリ画面(認証完了した実際の画面)
<?php
require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';
use Abraham\TwitterOAuth\TwitterOAuth;
if (requireLoginedSession()) {
$connection = new TwitterOAuth(
CUSTOMER_KEY,
CUSTOMER_SECRET,
$_SESSION['access_token']['oauth_token'],
$_SESSION['access_token']['oauth_token_secret']
);
try {
$statuses = $connection->get(
'favorites/list',
[
'screen_name' => $_SESSION['access_token']['screen_name'],
'count' => '20',
'include_entities' => 'true'
]
);
} catch (Exception $e) {
echo $e->getMessage();
die('Error!');
}
}
else {
//リダイレクト
header('Location: login.php');
exit();
}
//この後 $statuses から必要な「いいね」の情報を表示させる処理
アプリの認証が終わったら本来やりたかったことの手始めとして、「いいね」の一覧を表示させます。
1.5. finished.php
: 処理完了画面
<?php
require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';
use Abraham\TwitterOAuth\TwitterOAuth;
if (requireLoginedSession()) {
$connection = new TwitterOAuth(
CUSTOMER_KEY,
CUSTOMER_SECRET,
$_SESSION['access_token']['oauth_token'],
$_SESSION['access_token']['oauth_token_secret']
);
//post されたパラメータを受け取る
$checkedArray = $_POST['checked'];
//チェックした「いいね」を解除する
foreach ( $checkedArray as $val ) {
//$checkedArray は ツイート のIDの array
try {
$statuses = $connection->post(
'favorites/destroy',
[
'id' => $val
]
);
return $statuses;
} catch (Exception $e) {
echo $e->getMessage();
exit();
}
}
}
else {
//リダイレクト
header('Location: login.php');
exit();
}
続いて画面上でチェックし、チェックの付いたツイートのIDの array を $_POST
で受け取った後( $_POST['checked']
というパラメータとします)の処理です。
ここでは単純に foreach
でIDをループさせながらリクエストを投げることにしました。
ここの処理が、冒頭で書いた通り user context
が必要になるわけです。
1.6. logout.php
: ログアウト画面
<?php
require_once './config.php';
require_once './session.php';
if (requireLoginedSession()) {
//セッション破棄
sessionDestroy();
?>
echo 'ログアウト完了';
<?php
}
else {
//リダイレクト
header('Location: login.php');
exit();
}
?>
ログアウト時はセッション破棄。
実際はこの他に細かいことがあれやこれやありますが、要点は以上の通りです。
参考
Twitter API, OAuth
- 【PHP】新TwitterOAuthでログイン機能を実装する – Qiita
- TwitterOAuthでログイン認証をおこなう[OAuth]
- Response Codes – Twitter Developers
- POST favorites/destroy – Twitter Developers
- Authenticating users — Twitter Developers
- OAuth with the Twitter API — Twitter Developers
- TwitterOAuth PHP Library for the Twitter REST API