前回まででOpenWeatherApiから「現在の天気」が取得・表示できました。
次はツイッターから必要なデータを探してブラウザ表示させるまでを実装してゆきます。
準備
パッケージインストール
composer require abraham/twitteroauth
でパッケージをインストールしておいてください。
ルーティング
/api/tweets にGETアクセスすると、getTweetsメソッドに来るよう定義します。
Route::get('/tweets', [TwitterController::class, 'getTweets']);※api.php に設定したルートは、自動でurlに/apiが付与されるので実際のapiアクセス先は、/api/tweets となります
Twitter Api接続に必要なデータをconfigに追記
コントローラーで使いたいapi接続情報を、/config/const.php に追記します

OpenWeather用データの下に、twitter用のデータを書いています。
.envに本当のデータを定義して、configで.envを呼び出している形になります。
これをコントローラーで呼び出す部分は以下の通りです。

複数メソッドでツイッターに接続するので、__construct内でまとめて定義しています。
Serach Tweetの基本的な使い方
$tweetList = $this->connection
->get('/search/tweets', $tweets_params)
->statuses;上記でツイートが取得できます。
$this->connection : コンストラクタでnewしたTwitterOAuthインスタンスが入っています
->get(‘/search/tweets’, $tweets_params): 第一引数にurlを、第二引数に検索条件が入っています
↑↑この$tweet_paramsは、検索したい条件の配列です。以下のような値を定義しています。
$tweets_params = [ 'q' => '東京 天気', //検索したいキーワード 'count' => 10, //取得件数。デフォルトは15件 ];
‘q’以外は任意なので、必要に応じて変更してください。
返ってくるデータ
$this->connection->get(‘/search/tweets’, $tweets_params);
このコードで返ってくるデータは

こんな風にstatuses配下に収まっています。
なので取得時に ->statuses を書いておくことで、ひとつ階層を浅くできるので(satussesを省ける)書いておいたほうが後で楽だと思います。
エラー時
ちなみにエラー時は

errors が返ってきます。
実際に書いたツイッター取得用のコード(Controller)
上は基本的な使い方ですが、今回は天気・食べ物の2種類分apiを叩きたかったので
変数でキーワードを渡すなどして最終的に以下のようになりました。
ユーザー画面での、Osaka, Sapporo などselectBoxでの値変更がトリガーとなっています。
App\Http\Controllers\Api\TwitterController 内
public function getTweets(Request $request) // ajaxでここに来る
{
$destination = $request->destination;
//天気関連ツイート取得
$tweetWeatherList = $this->getTweetByKeywords($destination, '#イマソラ');
//食べ物関連ツイート取得
$tweetFoodList = $this->getTweetByKeywords($destination, '美味しい');
return response()->json( // jsonをJS側に返す
[
'weather' => $tweetWeatherList,
'food' => $tweetFoodList,
]
);
}
private function getTweetByKeywords($destination, $keyword) //実際のデータ取得関数
{
//検索キーワードを設定。 -をつけると除外検索ができる
$q = $destination . $keyword . ' -相互 filter:images -#相互RT exclude:retweets';
$tweets_params = [
'q' => $q,
'count' => config('const.api.twitter.settings.getNum'),
'tweet_mode' => 'extended',
];
$tweetList = $this->connection->get('/search/tweets', $tweets_params)->statuses;
//以下はbladeで画像を表示させるための準備なので
//必要ない場合もあります
foreach ($tweetList as $tweet) {
$tweet->mediaUrl = '画像なし'; //初期値
//画像urlを取得
$mediaExist = $tweet->extended_entities->media ?? '';
if ($mediaExist) {
$media = $tweet->extended_entities->media;
foreach ($media as $m) {
if ($m->type === 'photo') {
$tweet->mediaUrl = $m->media_url_https;
}
}
}
}
return $tweetList;
}これでJSからPHP側に値が渡ってきた場合の処理はかけましたので、JS側を書いてゆきます。
BladeからJS、JSからAjax送信
順番が前後しますが、フロント側の実装です。
ブラウザでselectBoxが選択された(changeイベント発生)がトリガーとなり、ajaxが走ります。
ajax
以下ajax部分のみ抜粋。
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
},
url: '/api/tweets', // api.phpに定義したルート
type: 'GET',
data: {
'destination': destination // selectboxで選ばれた地域名が入る
},
dataType: 'json',
})
.done(function (response) {
const makeTweetHtml = function (index, tweet) {
var block = '<div class="col">'
+ '<a href="https://twitter.com/' + tweet.user.screen_name + '/status/' + tweet.id_str + '" class="test-dark" target="_blank">'
+ '<p>画像:<img src="' + tweet.mediaUrl + '" class="img-fluid"></p>'
+ '<p>ツイート内容:' + tweet.full_text + '</p></a>'
+ '</div>';
targetDom.append(block);
}
//
//天気
//
var targetDom = $('#js_tweetWeatherWrap')
targetDom.html(""); //前回の取得内容をリセット
$.each(response.weather, makeTweetHtml)
//
//食べ物
//
var targetDom = $('#js_tweetFoodWrap')
targetDom.html(""); //前回の取得内容をリセット
$.each(response.food, makeTweetHtml)
})
.fail(function () {
console.log("failed");
})これで、セレクトボックスで選んだ地域名のお天気関連ツイート、食べ物関連ツイートがブラウザに表示されます。

食べ物関連ツイートは見切れていますが、ちゃんと設定した件数表示されています。
cssは未実装同然なのでどうにかしたいのですが、その前にこれをVue.jsに書き換えてから。。
実際考えながら書いていると時間がかかりましたが、まとめると1ページで収まるくらいシンプルですね。





