序章

このチュートリアルでは、 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が拡張され、ツイートが到着するとキューに配置されます。
  • 職人の命令、 ConnectToStreamingAPI、のインスタンスでストリーミングAPIへの接続を開きます TwitterStream
  • ジョブクラスProcessTweet、キューからプルされたときにツイートを処理するためのハンドラーが含まれます
  • A Tweet Eloquentモデル
  • ツイートウィジェットを表示するためのいくつかのブレードテンプレート

チュートリアルを読みながら、このGitHubリポジトリをフォローすることができます。 ステップごとに個別のコミットがあります。

https://github.com/dabernathy89/Laravel-Twitter-Streaming-API-Demo

ステップ1—新しいLaravelアプリを作成する

Laravel インストーラーを使用して、新しいLaravelインスタンスを作成します。

  1. laravel new twitter-stream-test

それが完了したら、アプリをHomestead構成ファイルに追加します。 あなたの編集を忘れないでください hosts 構成に追加したカスタムドメインを含むファイル。 ホームステッドを起動します。

  1. homestead up --provision

ホームステッドへのSSH:

  1. 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コマンドでジョブを作成できます。

  1. php artisan make:job ProcessTweet

これにより、にJobクラスが生成されます app/Jobs フォルダ。 今のところ、調整する必要があるのは2つだけです。

  1. このクラスがツイートを処理することはご存知でしょう(まだ設定していませんが)。 $ tweet変数をコンストラクターに渡し、それをプロパティとして設定します。
  2. のツイートで何かをする 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 ツイートをキューに簡単にプッシュできるようにする特性。
  • 方法は1つだけです。 enqueueStatus、ツイートごとにPhirehoseから呼び出されます。

ステップ5—登録する TwitterStream クラス

登録する必要があります TwitterStream Laravelコンテナでクラス化して、依存関係を適切に取り込むことができるようにします。 の中に register あなたの方法 AppServiceProvider クラスには、以下を追加します。

        $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();
    }
}

また、コマンド登録する必要があります。 更新するだけです $commands のプロパティ App\Console\Kernel クラス:

    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

また、データベースキューを準備するには、次のコマンドを実行する必要があります。

  1. php artisan queue:table
  1. php artisan migrate

ステップ9—いくつかのツイートを読んでください!

これで、いくつかのツイートの処理を開始する準備が整いました。 Artisanコマンドを実行します。

php artisan connect_to_streaming_api

Phirehoseからのコンソールの接続に関するいくつかの情報が表示されます。 ツイートが処理されるたびに通知されるわけではありませんが、接続のステータスが時々更新されます。

やがて、Scottch.ioがキューに並んでいることについてのツイートがいくつかあるはずです。 ツイートが届いているかどうかを確認するには、データベースにアクセスして、 jobs テーブル:

それでは、キューの処理を試してみましょう。 新しいシェルウィンドウを開き、Homesteadでアプリに移動して、最初のアイテムをキューから取り出します。

php artisan queue:work

すべてがうまくいけば、コンソールにツイートのテキストとIDが表示されます。 handle() のメソッド ProcessTweet 仕事。

ステップ10—ツイートモデルを設定する

Streaming APIに正常に接続できたので、注目のツイートウィジェットの作成を開始します。 を生成することから始めます Tweet モデルと対応するデータベースの移行:

  1. 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');
    }
}

最後に、データベースを移行します。

  1. 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つのツイートのみを表示できます。

ツイートを既存のものに渡します welcome のメインルートを更新して表示 routes.php ファイル:

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 両方のツイートリストに共通する小さな部分になります

The 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

リストに非常に基本的なスタイルを設定するには、次のCSSをリストに追加します。 app.blade.php ファイル:

        .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がキューリスナーを監視するために使用するスーパーバイザーを構成して、Artisanコマンドを監視し、失敗した場合は再起動することをお勧めします。
  • デプロイメントプロセスへのスーパーバイザーへの呼び出しを処理する必要があります。
  • 検索用語は変更される可能性があり、Phirehoseはスクリプトを中断せずにそれらを更新するためのメソッドを提供します。