PHPでTwitterに投稿(ツイート)する

(1/1)
Twitter - PHP
PHP で Twitter にメッセージを投稿(ツイート)するプログラムを作る。PHP5 でなければ動かなかったり、PEAR が必要なものが出回っているが、ここでは PHP 5 以上でフレームワークを必要としないプログラムを作ることを目標にする。

2010 年(平成 22 年)8 月から BASIC認証が利用できなくなったため、OAuth認証が利用できるようにサンプル・プログラムをバージョンアップした。
2013 年(平成 25 年)6 月から Twitter API 1.0 が利用できなくなったため、API 1.1 が利用できるようにサンプル・プログラムをバージョンアップした。
2014 年(平成 26 年)1 月から Twitter API 呼び出しが https のみとなったため、サンプル・プログラムをバージョンアップした。

サンプル・プログラムの実行例

PHPでTwitterに投稿(ツイート)する

サンプル・プログラム

OAuth認証処理を行うコードについては、「PHP4 で oAuth。Twitter API でつぶやく。『マチルダさ~ん』」(motooLogue)および「Twitter API の使い方まとめ」(シンカー)を参考にさせていただいた。便利なコードを公開されていることに感謝する。

OAuth認証のための準備

OAuth認証を利用する場合、事前の準備として、プログラムを Twitter に登録する必要がある。
まず、自分のアカウントで Twitter にログインし、Twitter Apps に進む。
Create New App」ボタンをクリックする。
すると「アプリケーション登録申請」画面になるので、必要な情報を以下のように入力していく。
アプリケーションのアイコン
このアプリケーションのアイコン。
アプリケーション名
実際に Twitter に投稿したときに表示される「from ****」の部分。日本語も登録できる。
アプリケーションの説明
適当に書いておけばよい。
アプリケーションのウェブサイト URL
「アプリケーション名」からリンクが張られるので、実際にプログラムがある URL を書く。
所属会社/団体
適当に書いておけばよい。
サイト
適当に書いておけばよい。
アプリケーションの種類
クライアントソフトを作るのか、ブラウザを利用するサービスなのかを指定する。ここではクライアントソフトにしておけばよい。
コールバック URL
上記で「ブラウザアプリケーション」を選んだ場合に記入しなければならない。
Default Access type
アプリケーションに与えられる権限。ここでは "Read & Write" を選んでおく。
Twitter でログインする
プログラムで Twitter にログインする場合にチェックする。ここではチェックしなくて良い。
CAPTCHAを入力し、[保存]ボタンをクリックすれば、アプリケーションの登録は完了する。
続いて「Application Details」というページに移動するので、そこで表示されている Cunsumer keyConsumer secret を記録しておく。これが OAuth認証で必要になる。
次に、http://dev.twitter.com/apps に移動する。
先ほど登録したアプリケーションが表示されているので、アプリケーション名をクリックする。するとアプリケーションの設定画面になる。右方にある "My Access Token" をクリックする。
Access Token (oauth_token)Access Token Secret (oauth_token_secret) が表示されるので、これも記録しておく。これも OAuth認証で必要になる。

PHP の https対応

Twitter API の呼び出しは https通信で行うため、PHP に OpenSSL モジュールが組み込まれている必要がある。
関数  phpinfo  を使って、下図のように表示されればOK。
OpenSSL - PHP
そうでない場合は、次の手順に従って OpenSSL を有効化し、PHP を再起動させる必要がある。

Windows では、phop.ini の下記の行を有効化する。

extension=php_openssl.dll



Linux では --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSL インストール手順

これで準備は完了だ。

解説:pahooTwitterAPI クラス

0022:     //OAuth用パラメータ
0023:     // https://apps.twitter.com/
0024:     var $TWTR_CONSUMER_KEY    = '***************';  //Cunsumer key
0025:     var $TWTR_CONSUMER_SECRET = '***************';  //Consumer secret
0026:     var $TWTR_ACCESS_KEY      = '***************';  //Access Token (oauth_token)
0027:     var $TWTR_ACCESS_SECRET   = '***************';  //Access Token Secret (oauth_token_secret)

各種WebAPI を使うメソッドは、PHP のクラスを使って定義している。
クラスについては「PHP でクラスを使ってテキストの読みやすさを調べる」で解説している。
クラスファイル "pahooTwitterAPI" は、組み込み関数  require_once  を使って読めるディレクトリに配置する。ディレクトリは、設定ファイル php.ini に記述されているオプション設定 include_path に設定しておく。

先ほど記録した文字列を下記の定数に設定していく。
TWTR_CONSUMER_KEYCunsumer key
TWTR_CONSUMER_SECRETConsumer secret
TWTR_ACCESS_KEYAccess Token (oauth_token)
TWTR_ACCESS_SECRETAccess Token Secret (oauth_token_secret)

Twitter API:POST statuses/update

ツイートするには、「Twitter API:POST statuses/update」を用いる。
Twitter API (POST)
URL
https://api.twitter.com/1.1/statuses/update.json

入力パラメータ
項目名 フィールド名 内  容
投稿文 status string 【必須】投稿文。UTF-8でエンコードされたテキストで、140文字以下。
応答データ(一部)(json) id_str 投稿ID created_at 投稿日時 text 投稿文 user screen_name ユーザー名 retweet_count リツイート回数

解説:リクエスト

0105: /**
0106:  * URLエンコード RFC3986版
0107:  * @param string $str エンコードするテキスト
0108:  * @return string エンコード結果
0109: */
0110: function _rawurlencode($str) {
0111:     $str = str_replace(array('+', '%7E'), array('%20', '~'), $str) ;
0112:     $str = rawurlencode($str);
0113: 
0114:     return $str;
0115: }
0116: 
0117: /**
0118:  * Twitter API:アクセストークンを用いたリクエスト(ユーザー認証あり)
0119:  * @param string $url    TwitterAPIのリクエストURL
0120:  * @param string $method GET|POST
0121:  * @param array  $option オプションパラメータ配列
0122:  * @return bool TRUE:リクエスト成功/FALSE:失敗
0123: */
0124: function request_user($url$method$option) {
0125:     //キー生成
0126:     $signature_key = $this->_rawurlencode($this->TWTR_CONSUMER_SECRET) . '&' . $this->_rawurlencode($this->TWTR_ACCESS_SECRET);
0127: 
0128:     //パラメータ
0129:     $params = array(
0130:         'oauth_token'             => $this->TWTR_ACCESS_KEY,
0131:         'oauth_consumer_key'     => $this->TWTR_CONSUMER_KEY,
0132:         'oauth_signature_method' => 'HMAC-SHA1',
0133:         'oauth_timestamp'         => time(),
0134:         'oauth_nonce'             => microtime(),
0135:         'oauth_version'         => '1.0'
0136:     );
0137:     $params = array_merge($option$params);
0138:     ksort($params) ;
0139: 
0140:     //リクエスト文字列生成
0141:     $request_params = http_build_query($params, '', '&');
0142:     $request_params = $this->_rawurlencode($request_params);
0143:     $encoded_request_method = $this->_rawurlencode($method);
0144:     $encoded_request_url = $this->_rawurlencode($url);
0145: 
0146:     //シグネチャ生成
0147:     $signature_data = $encoded_request_method . '&' . $encoded_request_url . '&' . $request_params;
0148:     $hash = hash_hmac('sha1', $signature_data$signature_keyTRUE);
0149:     $signature = base64_encode($hash);
0150:     $params['oauth_signature'] = $signature;
0151: 
0152:     //ヘッダ文字列生成
0153:     $header_params = http_build_query($params, '', ',');
0154: 
0155:     //リクエスト用コンテキスト
0156:     $context = array(
0157:         'http' => array(
0158:             'method' => $method,         //リクエストメソッド
0159:             'header' => array(               //ヘッダー
0160:                 'Authorization: OAuth ' . $header_params
0161:             ),
0162:         ),
0163:     );
0164: 
0165:     //オプション処理
0166:     if (count($option) > 0) {
0167:         if ($method == 'GET') {
0168:             $url .= '?' . http_build_query($option);
0169:         } else {
0170:             $context['http']['content'] = http_build_query($option) ;
0171:         }
0172:     }
0173: 
0174:     // cURLを使ってリクエスト
0175:     $curl = curl_init() ;
0176:     curl_setopt($curl, CURLOPT_URL , $url);
0177:     curl_setopt($curl, CURLOPT_HEADER, 1) ; 
0178:     curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $context['http']['method']);
0179:     curl_setopt($curlCURLOPT_SSL_VERIFYPEER , FALSE);  //証明書は無視
0180:     curl_setopt($curlCURLOPT_RETURNTRANSFERTRUE);        //結果を文字列で
0181:     curl_setopt($curl, CURLOPT_HTTPHEADER, $context['http']['header']);
0182:     if (isset($context['http']['content']) && !empty($context['http']['content'])) {
0183:         curl_setopt($curl, CURLOPT_POSTFIELDS, $context['http']['content']);         //リクエストボディ
0184:     }
0185:     curl_setopt($curl, CURLOPT_TIMEOUT, 5);
0186:     $res1 = curl_exec($curl);
0187:     $res2 = curl_getinfo($curl);
0188:     curl_close($curl);
0189: 
0190:     //結果処理
0191:     $this->webapi = $url;
0192:     $json = substr($res1$res2['header_size']);
0193:     $this->responses = json_decode($jsonFALSE, 512, JSON_BIGINT_AS_STRING);
0194:     if (isset($this->responses->errors)) {
0195:         $this->error   = TRUE;
0196:         $this->errmsg  = $this->responses->errors[0]->message;
0197:         $this->errcode = $this->responses->errors[0]->code;
0198:     }
0199: 
0200:     return (! $this->error);
0201: }

Twitter API へのリクエスト処理は、ユーザー関数 request で行う。大部分は OAuth認証のための処理である。
戻り値は JSON 形式である。結果をデコードし、クラス変数 $responses に代入しておく。同時にエラー判定も行う。

解説:ツイート

0321: /**
0322:  * 投稿する
0323:  * @param string $message 投稿メッセージ(UTF-8限定)
0324:  * @return bool TRUE:リクエスト成功/FALSE:失敗
0325: */
0326: function tweet($message) {
0327:     $url    = 'https://api.twitter.com/1.1/statuses/update.json';
0328:     $method = 'POST' ;
0329:     $option = array('status' => $message);
0330: 
0331:     return $this->request_user($url$method$option);
0332: }
0333: 
0334: /**
0335:  * メディア付き投稿
0336:  * @param string $message 投稿メッセージ(UTF-8限定)
0337:  * @param array  $fnames  メディアデータのファイル名(配列)
0338:  * @return bool TRUE:リクエスト成功/FALSE:失敗
0339: */
0340: function tweet_media($message$fnames) {
0341:     static $url_upload    = 'https://upload.twitter.com/1.1/media/upload.json';
0342:     static $url_tweet     = 'https://api.twitter.com/1.1/statuses/update.json';
0343:     static $method        = 'POST' ;
0344: 
0345:     //メディアのアップロード
0346:     $media_ids = '';
0347:     $cnt = 0;
0348:     foreach ($fnames as $fname) {
0349:         $data = @file_get_contents($fname);
0350:         $media_id = $this->upload($url_upload, 'POST', 'media_data', $data);
0351:         if ($media_id == NULL)      break;
0352:         if ($cnt > 0)   $media_ids .= ',';
0353:         $media_ids .= $media_id;
0354:         $cnt++;
0355:         if ($cnt > 3)   break;       //最大4つまで
0356:     }
0357: 
0358:     //ツイート
0359:     if (! $this->error) {
0360:         $option = array('status' => $message, 'media_ids' => $media_ids);
0361:         $res = $this->request_user($url_tweet$method$option);
0362:     } else {
0363:         $res = FALSE;
0364:     }
0365: 
0366:     return $res;
0367: }

ツイートは、Twitter API の "POST statuses/update" を用いる。
先ほど紹介したユーザー関数 request に対し、リクエスト URL、メソッド(POST または GET)、投稿文を渡すだけで完了である。

解説:メイン・プログラム

0025: //PHP5判定
0026: if (! isphp5over()) {
0027:     echo 'Error > Please let me run on PHP5 or more...';
0028:     exit(1);
0029: }
0030: 
0031: //Twitter API クラス
0032: require_once('pahooTwitterAPI.php');

0130: $msg = isset($_POST['exec']) ? getParam('msg', TRUE, '') : '';
0131: $ptw = new pahooTwitterAPI();
0132: $outmsg = '';
0133: 
0134: if ($msg != '') {
0135:     $msg = htmlspecialchars($msg);
0136:     if ($ptw->twitter_strlen($msg) <= 140) {
0137:         $res = $ptw->tweet($msg);
0138:         if ($res == FALSE) {
0139:             $outmsg = '<p style="text:red;">投稿失敗:' . $ptw->errmsg . '</p>';
0140:         } else {
0141:             $id_str = (string)$ptw->responses->id_str;
0142:             $url = 'https://twitter.com/' . (string)$ptw->responses->user->screen_name . '/status/' . $id_str;
0143:             $outmsg = '<p>投稿成功:<a href="' . $url . '">' . $url . '</a></p>';
0144:         }
0145:     } else {
0146:         $outmsg = '<p style="text:red;">メッセージを 140 文字以下にしてください.</p>';
0147:     }
0148: }
0149: $HtmlBody = makeCommonBody($msg$outmsg);
0150: 
0151: // 表示処理
0152: echo $HtmlHeader;
0153: echo $HtmlBody;
0154: echo $HtmlFooter;

メイン・プログラムは、冒頭で PHP5 以上かどうかの判定を行い、クラス "'pahooTwitterAPI.php" を読み込む。

一度に投稿できるツイートは、半角でも全角でも 140 文字以下なので、入力文字数のチェックをしておく。
ユーザー関数 twitter_strlen は、英数字も日本語も 1 文字としてカウントするが、URL のみ 23 文字としてカウントする Twitter 仕様である。140 文字を超えた場合にはツイートしない。

tweet を実行した後、戻り値を解析し、成功した場合には投稿メッセージへのリンクを表示する。

Twitterへの再登録が必要な場合も

https 対応のバージョンアップしたプログラムを、以前のアクセストークンのまま利用しようとしたのだが、Twitter API がエラーを返してくる。そこで、新しいプログラムとして登録したところ、なぜが正常に動作した。

プログラムのバージョンアップで正常に動作しない場合は、Twitter へ新規登録してみるといいだろう。

参考サイト

参考書籍

表紙 Twitter API ポケットリファレンス
著者 山本裕介
出版社 技術評論社
サイズ 単行本
発売日 2011年07月
価格 2,678円(税込)
rakuten
ISBN 9784774147321
Twitter APIの機能を完全解剖!最新のAPI群もサンプルコードを交えてわかりやすく解説。PHP、Java、Ruby、Pythonなどメジャーな言語でTwitter APIを自在にプログラミング。ライブラリのセットアップ方法、JSON、OAuthなど重要な技術要素も、総合的に解説。この1冊でTwitter APIの全機能がわかる、使える、開発できる。
 
表紙 Twitter APIリファレンスガイドブック
著者 池田成樹
出版社 カットシステム
サイズ 単行本
発売日 2010年09月
価格 3,240円(税込)
rakuten
ISBN 9784877832438
つぶやく世界をプログラミング。OAuth認証+Ruby+twurl環境でのAPI呼び出しを紹介。
 
(この項おわり)
header