Laravelを使用してリアルタイムでツイートを処理する方法
序章
このチュートリアルでは、 Twitter Streaming API を使用して、Laravelアプリケーションからのツイートをリアルタイムで処理する方法を示します。 これにはさまざまな使用例があります。たとえば、会社の言及に自動応答したり、Twitterでコンテストを実行したり、ユーザーが製品について不満を言ったときにサポートチケットを作成したりする場合があります。 このチュートリアルでは、承認されたツイートをアプリのホームページに表示するための「注目のツイート」ウィジェットを作成します。
多くの開発者が精通しているTwitterRESTAPIを最初に見るかもしれません。 これらのAPIを使用すると、アプリユーザーに代わってツイートを読み書きしたり、フォロワーやリストを管理したりするなど、多くの優れた機能を実行できます。 ただし、送信されたツイートを処理する場合、RESTAPIの管理は非常に困難です。 ページネーションとレート制限は、すぐにロジスティックの悪夢になります。
REST APIはリクエスト情報を強制しますが、ストリーミングAPIはフィード情報を提供します。 ドキュメントでどのように機能するかについて詳しく読むことができますが、基本的にはTwitterからアプリケーションへのパイプであり、ツイートの継続的なフローを提供します。
チュートリアルが終了するまでに、アプリ内のツイートのコレクションが常に更新され、ホームページに表示するために承認または不承認にすることができます。 これが最終的な結果のプレビューです。
概要
道具
- パブリックストリーミングAPI: 3つのストリーミングAPIがありますが、私たちが気にするのはパブリックAPI、より具体的には「フィルター」エンドポイントです。 このエンドポイントは、定義したキーワードでフィルタリングされた、すべての公開ツイートのストリームを配信します。
- Phirehose: Phirehose ライブラリは、ストリーミングAPIの認証およびその他の実装の詳細を処理します。
- ホームステッド:選択した環境でアプリを作成できますが、このチュートリアルでは、ホームステッドを使用していることを前提としています。
ノート
- ストリーミングAPIは、Twitterによって特別に扱われます。 1つのTwitterアプリから開くことができる接続は1つだけです。
- Streaming APIへの接続には特別な性質があるため、アプリのWebに面する部分から分離することが重要です。 このチュートリアルでは、Artisanコンソールコマンドを使用して接続を作成します。
- ストリーミングAPIは非常に扱いにくいため、ツイートを収集しているのと同じプロセスで、ツイートを集中的に実行しないことが重要です。 このチュートリアルでは、ツイートをキューに入れるだけです。
- 追跡している用語に注意してください。 人気のある有名人のすべての言及を追跡しようとすると、アプリはおそらく溶けてしまいます。
アプリの構造
作成するアプリの主な部分は次のとおりです。
TwitterStream
と呼ばれるクラス。これは、Phirehoseを拡張し、ツイートが到着するとキューに配置します。TwitterStream
のインスタンスを使用してストリーミングAPIへの接続を開くArtisanコマンドConnectToStreamingAPI
- ジョブクラス、
ProcessTweet
。これには、ツイートがキューから削除されたときにツイートを処理するためのハンドラーが含まれます。 Tweet
Eloquentモデル- ツイートウィジェットを表示するためのいくつかのブレードテンプレート
チュートリアルを読みながら、このGitHubリポジトリをフォローすることができます。 ステップごとに個別のコミットがあります。
https://github.com/dabernathy89/Laravel-Twitter-Streaming-API-Demo
ステップ1—新しいLaravelアプリを作成する
Laravel インストーラーを使用して、新しいLaravelインスタンスを作成します。
laravel new twitter-stream-test
それが完了したら、アプリをHomestead構成ファイルに追加します。 構成に追加したカスタムドメインを使用して、hosts
ファイルを編集することを忘れないでください。 ホームステッドを起動します。
homestead up --provision
ホームステッドへのSSH:
homestead ssh
最後に、cd
をアプリのフォルダーに入れます。
ステップ2—Phirehoseをインストールします
次に、Phirehoseライブラリをプルする必要があります。 composer require fennb/phirehose
を実行して、最新バージョンを取得します。 PhirehoseはPSR-0またはPSR-4の自動読み込みをサポートしていないため、Composerのclassmap
自動読み込みオプションを使用する必要があります。 database
エントリの直後に行を追加します。
"classmap": [ "database", "vendor/fennb/phirehose/lib" ],
ステップ3—ProcessTweet
ジョブを作成する
概要で、StreamingAPIからのすべてのツイートをキューに入れることを説明しました。 Laravel 5.2には、キュー内のアイテムを処理するための特別なジョブクラスがあります。 アプリにはProcessTweet
というジョブがあり、キューからツイートを引き出して何かを実行します。 簡単なArtisanコマンドでジョブを作成できます。
php artisan make:job ProcessTweet
これにより、app/Jobs
フォルダーにJobクラスが生成されます。 今のところ、調整する必要があるのは2つだけです。
- このクラスがツイートを処理することはご存知でしょう(まだ設定していませんが)。 $ tweet変数をコンストラクターに渡し、それをプロパティとして設定します。
handle()
メソッドのツイートで何かをします。 今のところ、ツイートからいくつかの基本的な情報をvar_dump()
することができます。
<?php namespace App\Jobs; use App\Jobs\Job; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class ProcessTweet extends Job implements ShouldQueue { use InteractsWithQueue, SerializesModels; protected $tweet; /** * Create a new job instance. * * @return void */ public function __construct($tweet) { $this->tweet = $tweet; } /** * Execute the job. * * @return void */ public function handle() { $tweet = json_decode($this->tweet,true); var_dump($tweet['text']) . PHP_EOL; var_dump($tweet['id_str']) . PHP_EOL; } }
ステップ4—TwitterStream
クラスを作成する
Phirehoseを使用するには、基本のPhirehoseクラスを拡張する単純なクラスを作成する必要があります。 これはどこにでも移動できますが、app
フォルダーに直接配置しました。 フルクラスは次のとおりです。
<?php namespace App; use OauthPhirehose; use App\Jobs\ProcessTweet; use Illuminate\Foundation\Bus\DispatchesJobs; class TwitterStream extends OauthPhirehose { use DispatchesJobs; /** * Enqueue each status * * @param string $status */ public function enqueueStatus($status) { $this->dispatch(new ProcessTweet($status)); } }
注意すべき点がいくつかあります。
- クラスは
DispatchesJobs
トレイトをプルして、ツイートをキューに簡単にプッシュできるようにします。 enqueueStatus
という1つのメソッドしかありません。このメソッドは、ツイートごとにPhirehoseによって呼び出されます。
ステップ5—TwitterStream
クラスを登録する
TwitterStream
クラスをLaravelコンテナに登録して、依存関係を適切に取り込むことができるようにする必要があります。 AppServiceProvider
クラスのregister
メソッドに、次を追加します。
$this->app->bind('App\TwitterStream', function ($app) { $twitter_access_token = env('TWITTER_ACCESS_TOKEN', null); $twitter_access_token_secret = env('TWITTER_ACCESS_TOKEN_SECRET', null); return new TwitterStream($twitter_access_token, $twitter_access_token_secret, Phirehose::METHOD_FILTER); });
また、サービスプロバイダーの上部にuse Phirehose;
とuse App\TwitterStream;
を追加する必要があります。 今のところ、環境変数について心配する必要はありません。まもなく作成します。
ステップ6—職人コマンドを作成する
Artisanコマンドを生成して、コマンドラインからストリーミングAPI接続を開始できるようにします。
php artisan make:console ConnectToStreamingAPI
これにより、定型コンソールコマンドクラスが生成されます。 次に、次のことを行う必要があります。
- コマンドの署名と説明を更新します
- コンストラクターを介して
TwitterStream
クラスのインスタンスをプルします - コマンドの
handle()
メソッドで、検索語を含むPhirehoseオブジェクトの構成を完了し、接続を開きます
完成したコマンドは次のようになります。 キーワードscotch_io
を含むツイートを取り込みます。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use App\TwitterStream; class ConnectToStreamingAPI extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'connect_to_streaming_api'; /** * The console command description. * * @var string */ protected $description = 'Connect to the Twitter Streaming API'; protected $twitterStream; /** * Create a new command instance. * * @return void */ public function __construct(TwitterStream $twitterStream) { $this->twitterStream = $twitterStream; parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $twitter_consumer_key = env('TWITTER_CONSUMER_KEY', ''); $twitter_consumer_secret = env('TWITTER_CONSUMER_SECRET', ''); $this->twitterStream->consumerKey = $twitter_consumer_key; $this->twitterStream->consumerSecret = $twitter_consumer_secret; $this->twitterStream->setTrack(array('scotch_io')); $this->twitterStream->consume(); } }
また、コマンドを登録する必要があります。 App\Console\Kernel
クラスの$commands
プロパティを更新するだけです。
protected $commands = [ Commands\ConnectToStreamingAPI::class ];
ステップ7—Twitterアプリを作成する
Twitterでアプリを生成し、キーとアクセストークンを取得します。 それらを.env
ファイルに追加します。
TWITTER_CONSUMER_KEY=KEY TWITTER_CONSUMER_SECRET=SECRET TWITTER_ACCESS_TOKEN=TOKEN TWITTER_ACCESS_TOKEN_SECRET=SECRET
ステップ8—キュードライバーを構成する
キューは好きなように設定できますが、デモンストレーションの目的で、データベースドライバーは正常に機能します。 これを設定するには、.env
ファイルを更新します。
QUEUE_DRIVER=database
デフォルトでは、アプリはhomestead
という名前のデータベースを検索します。 アプリ用に別のデータベースが必要な場合は、.env
ファイルでこれを更新することを忘れないでください。
DB_DATABASE=twitterstreamtest
また、データベースキューを準備するには、次のコマンドを実行する必要があります。
php artisan queue:table
php artisan migrate
ステップ9—いくつかのツイートを読んでください!
これで、いくつかのツイートの処理を開始する準備が整いました。 Artisanコマンドを実行します。
php artisan connect_to_streaming_api
Phirehoseからのコンソールの接続に関するいくつかの情報が表示されます。 ツイートが処理されるたびに通知されるわけではありませんが、接続のステータスが時々更新されます。
やがて、Scottch.ioがキューに並んでいることについてのツイートがいくつかあるはずです。 ツイートが届いているかどうかを確認するには、データベースにアクセスして、jobs
テーブルを確認してください。
それでは、キューの処理を試してみましょう。 新しいシェルウィンドウを開き、Homesteadでアプリに移動して、最初のアイテムをキューから取り出します。
php artisan queue:work
すべてがうまくいけば、ProcessTweet
ジョブのhandle()
メソッドから、コンソールにツイートのテキストとIDが表示されます。
ステップ10—ツイートモデルを設定する
Streaming APIに正常に接続できたので、注目のツイートウィジェットの作成を開始します。 Tweet
モデルと対応するデータベース移行を生成することから始めます。
php artisan make:model Tweet --migration
モデルにいくつかのプロパティを追加するので、先に進んでそれらを設定します。 完成したモデルと移行は次のようになります。TwitterIDは大量であるため、モデルIDに文字列を使用していることに注意してください。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Tweet extends Model { protected $fillable = ['id','json','tweet_text','user_id','user_screen_name','user_avatar_url','public','approved']; }
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTweetsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('tweets', function (Blueprint $table) { $table->string('id'); $table->text('json'); $table->string('tweet_text')->nullable(); $table->string('user_id')->nullable(); $table->string('user_screen_name')->nullable(); $table->string('user_avatar_url')->nullable(); $table->boolean('approved'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('tweets'); } }
最後に、データベースを移行します。
php artisan migrate
ステップ11—ProcessTweetジョブを便利にする
現在、ProcessTweet
ジョブは、コンソールにツイートに関する情報を表示しているだけです。 handle
メソッドを更新して、ツイートをデータベースに保存します。
public function handle() { $tweet = json_decode($this->tweet,true); $tweet_text = isset($tweet['text']) ? $tweet['text'] : null; $user_id = isset($tweet['user']['id_str']) ? $tweet['user']['id_str'] : null; $user_screen_name = isset($tweet['user']['screen_name']) ? $tweet['user']['screen_name'] : null; $user_avatar_url = isset($tweet['user']['profile_image_url_https']) ? $tweet['user']['profile_image_url_https'] : null; if (isset($tweet['id'])) { Tweet::create([ 'id' => $tweet['id_str'], 'json' => $this->tweet, 'tweet_text' => $tweet_text, 'user_id' => $user_id, 'user_screen_name' => $user_screen_name, 'user_avatar_url' => $user_avatar_url, 'approved' => 0 ]); } }
それが完了したら、キューリスナーを実行してキューを空にし、ツイートをデータベースにインポートできます。
php artisan queue:listen
これで、データベースにいくつかのツイートが表示されるはずです。
ステップ12—認証を設定する
Laravelの認証スキャフォールディングのおかげで、これはおそらく最も簡単なステップです。 とにかく走れ:
php artisan make:auth
ステップ13—ツイートをウェルカムビューに渡す
今のところ、アプリはメインのランディングページに注目のツイートウィジェットのみを表示します。 認証されたユーザーは、ツイートを承認または却下できるようになるため、すべてのツイートを受信します(ページ分割)。 訪問者は、最近承認された5つのツイートのみを表示できます。
routes.php
ファイルのメインルートを更新して、ツイートを既存のwelcome
ビューに渡します。
Route::get('/', function () { if (Auth::check()) { $tweets = App\Tweet::orderBy('created_at','desc')->paginate(5); } else { $tweets = App\Tweet::where('approved',1)->orderBy('created_at','desc')->take(5)->get(); } return view('welcome', ['tweets' => $tweets]); });
ステップ14—ブレードテンプレートを作成する
注目のツイートウィジェット用に3つのブレードテンプレートを作成する必要があります。これらはすべてresources/views/tweets
ディレクトリに保存されています。
list.blade.php
は最近のツイートの公開リストになりますlist-admin.blade.php
は、すべてのツイートの管理者向けリストになりますtweet.blade.php
は、両方のツイートリストに共通する小さな部分になります
list-admin
ビューは最も複雑です。 リストはフォームにラップされており、登録ユーザーがツイートを簡単に承認できるように、いくつかの無線入力が含まれています。
3つのテンプレートを順番に示します。
// list.blade.php @foreach($tweets as $tweet) <div class="tweet"> @include('tweets.tweet') </div> @endforeach
// list-admin.blade.php <form action="/approve-tweets" method="post"> {{ csrf_field() }} @foreach($tweets as $tweet) <div class="tweet row"> <div class="col-xs-8"> @include('tweets.tweet') </div> <div class="col-xs-4 approval"> <label class="radio-inline"> <input type="radio" name="approval-status-{{ $tweet->id }}" value="1" @if($tweet->approved) checked="checked" @endif > Approved </label> <label class="radio-inline"> <input type="radio" name="approval-status-{{ $tweet->id }}" value="0" @unless($tweet->approved) checked="checked" @endif > Unapproved </label> </div> </div> @endforeach <div class="row"> <div class="col-sm-12"> <input type="submit" class="btn btn-primary" value="Approve Tweets"> </div> </div> </form> {!! $tweets->links() !!}
// tweet.blade.php <div class="media"> <div class="media-left"> <img class="img-thumbnail media-object" src="{{ $tweet->user_avatar_url }}" alt="Avatar"> </div> <div class="media-body"> <h4 class="media-heading">{{ '@' . $tweet->user_screen_name }}</h4> <p>{{ $tweet->tweet_text }}</p> <p><a target="_blank" href="https://twitter.com/{{ $tweet->user_screen_name }}/status/{{ $tweet->id }}"> View on Twitter </a></p> </div> </div>
ステップ15-ウェルカムビューにウィジェットを表示する
ブレードテンプレートの準備ができたら、それらをwelcome
ビューに表示できます。
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="tweet-list"> @if(Auth::check()) @include('tweets.list-admin') @else @include('tweets.list') @endif </div> </div> </div> </div> @endsection
リストに非常に基本的なスタイルを設定するには、app.blade.php
ファイルに次のCSSを追加します。
.tweet { padding: 10px; border: 1px solid #ccc; border-radius: 5px; margin-bottom: 20px; }
これで、ウィジェットを表示できるようになりました。 ブラウザに移動して、アプリのホームページにアクセスします。 ツイートが表示されない場合は、キューリスナー(php artisan queue:listen
)を実行して、まだ含まれている可能性のあるものをすべて処理してください。 許可されたユーザーには、次のようなものが表示されます(さらにいくつかのツイートがあり、ぼやけが少なくなっています)。
ステップ16—ツイートを承認するためのルートを追加する
最後のステップは、ステップ14の管理者リストを機能させることです。 list-admin
テンプレートのフォームは、現在、存在しないルートを指しています。 routes.php
ファイルに追加する必要があります。 そのルート内で、ツイートを承認または却下するための基本的なロジックを実行します。 外観は次のとおりです。
Route::post('approve-tweets', ['middleware' => 'auth', function (Illuminate\Http\Request $request) { foreach ($request->all() as $input_key => $input_val) { if ( strpos($input_key, 'approval-status-') === 0 ) { $tweet_id = substr_replace($input_key, '', 0, strlen('approval-status-')); $tweet = App\Tweet::where('id',$tweet_id)->first(); if ($tweet) { $tweet->approved = (int)$input_val; $tweet->save(); } } } return redirect()->back(); }]);
このルートを設定すると、ツイートを承認済みまたは不承認としてマークできるようになります。 一部を承認してから、認証されていないユーザーとしてページにアクセスしてください。 次のようになります。
結論
それでおしまい! LaravelアプリをTwitterStreamingAPIに接続しました。 ただし、完全に本番環境に対応しているわけではありません。 考慮すべき他のいくつかのことがあります:
- Laravelがキューリスナーを監視するために使用するスーパーバイザー[1]を構成して、Artisanコマンドを監視し、失敗した場合は再起動することをお勧めします。
- デプロイメントプロセスへのスーパーバイザーへの呼び出しを処理する必要があります。
- 検索用語は変更される可能性があり、Phirehoseはスクリプトを中断せずにそれらを更新するためのメソッドを提供します。