如何使用Laravel实时处理推文

来自菜鸟教程
跳转至:导航、​搜索

介绍

本教程将展示如何使用 Twitter Streaming APIs 实时处理来自 Laravel 应用程序的推文。 有多种用例:也许您想自动回复提及您的公司,通过 Twitter 举办比赛,或者在用户抱怨您的产品时创建支持票。 在本教程中,我们将构建一个“特色推文”小部件,以在我们的应用程序主页上显示已批准的推文。

您可能会首先查看许多开发人员熟悉的 Twitter REST API。 这些 API 允许您做很多很酷的事情:代表应用程序用户读写推文、管理关注者和列表等等。 但是,如果您想在发送推文时对其进行处理,则 REST API 很难管理。 分页和速率限制很快成为后勤噩梦。

REST API 强制您 请求 信息,而流式 API 向您提供 信息。 您可以在 文档 中阅读有关它如何工作的更多信息,但它基本上是从 Twitter 到您的应用程序的管道,它提供持续的推文流。

在本教程结束时,您将在您的应用程序中拥有不断更新的推文集合,您可以批准或不批准这些推文显示在您的主页上。 这是您最终会得到的预览。

概述

工具

  • Public Streaming API: 共有三个 Streaming API,但我们关心的是公共 API——更具体地说,是“过滤器”端点。 此端点将提供所有公共推文的流,按您定义的关键字过滤。
  • Phirehose: Phirehose 库负责流式处理 API 的身份验证和其他实现细节。
  • Homestead: 虽然您可以使用您选择的环境构建您的应用程序,但本教程将假设您使用的是 Homestead

笔记

  • Twitter 对 Streaming API 进行了特殊处理。 您只能从一个 Twitter 应用程序打开一个连接。
  • 由于与 Streaming API 的连接具有特殊性质,因此将其与应用程序的面向 Web 的部分分开是很重要的。 在本教程中,我们将使用 Artisan 控制台命令创建连接。
  • 由于 Streaming API 非常挑剔,重要的是不要在收集推文的同一进程中 对推文做任何 密集操作。 在本教程中,您只需将推文放入队列中。
  • 请注意您正在跟踪的条款。 如果您尝试跟踪所有提及某个受欢迎的名人,您的应用程序可能会崩溃。

应用结构

以下是我们将要创建的应用程序的主要部分:

  • 一个名为 TwitterStream 的类,它将扩展 Phirehose 并在推文到达时将推文放入队列
  • 一个 Artisan 命令 ConnectToStreamingAPI,它将使用 TwitterStream 的实例打开与 Streaming API 的连接
  • 一个 作业类ProcessTweet,它将包含处理推文时从队列中拉出时处理推文的处理程序
  • A 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

接下来,您需要拉入 Phihose 库。 运行 composer require fennb/phirehose 以获取最新版本。 Phirehose 不支持 PSR-0 或 PSR-4 自动加载,因此您需要使用 Composer 的 classmap 自动加载选项。 在 database 条目之后添加一行:

        "classmap": [
            "database",
            "vendor/fennb/phirehose/lib"
        ],

第 3 步 — 创建 ProcessTweet 作业

我在概述中提到,我们将把来自 Streaming API 的所有推文放到一个队列中。 在 Laravel 5.2 中,有一些特殊的 Job 类 用于处理队列中的项目。 您的应用程序将有一个名为 ProcessTweet 的工作,它将负责将推文从队列中拉出并对其进行处理。 您可以使用简单的 Artisan 命令创建作业:

php artisan make:job ProcessTweet

这将在您的 app/Jobs 文件夹中生成一个 Job 类。 您现在只需要对其进行两次调整。

  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 特征,以便轻松地将推文推送到队列中。
  • 只有一个方法 enqueueStatus 将由 Phirehose 为每条推文调用。

第 5 步 — 注册 TwitterStream

您需要在 Laravel 容器中注册 TwitterStream 类,以便它可以正确地拉入其依赖项。 在 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 命令

生成 Artisan 命令,以便您可以通过命令行启动 Streaming 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 应用程序

用推特生成应用程序,获取密钥和访问令牌。 将它们添加到您的 .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 的控制台中看到有关连接的一些信息。 它不会在每次处理推文时告诉您,但它会不时地为您提供有关连接状态的更新。

不久之后,您应该会有一些关于 Scotch.io 的推文排在队列中。 要检查是否有推文进入,请转到您的数据库并查看 jobs 表:

现在让我们尝试处理队列。 打开一个新的 shell 窗口,导航到 Homestead 中的应用程序,然后将第一项从队列中拉出:

php artisan queue:work

如果一切顺利,您应该会在控制台中看到推文的文本和 ID,来自 ProcessTweet 作业中的 handle() 方法。

第 10 步 — 设置推文模型

现在您已成功连接到 Streaming API,是时候开始构建您的精选推文小部件了。 首先生成一个 Tweet 模型和相应的数据库迁移:

php artisan make:model Tweet --migration

我们将为我们的模型添加一些属性,所以现在继续设置它们。 下面是您完成的模型和迁移的样子 - 请注意,我使用字符串作为模型 ID,因为 Twitter 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 的 auth 脚手架,这可能是最简单的一步。 赶紧跑:

php artisan make:auth

第 13 步 - 将推文传递到欢迎视图

目前,您的应用将仅在主登录页面上显示精选推文小部件。 经过身份验证的用户将被允许批准或不批准推文,因此他们将收到所有推文(分页)。 访问者将只能看到最近批准的五条推文。

通过更新 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 步 — 创建刀片模板

您需要为特色推文小部件创建三个刀片模板,全部存储在 resources/views/tweets 目录中:

  • list.blade.php 将是面向公众的近期推文列表
  • list-admin.blade.php 将是所有推文的面向管理员的列表
  • tweet.blade.php 将是两个推文列表的一小部分共同点

list-admin 视图是最复杂的。 该列表包含在一个表单中,并包含一些无线电输入,以便注册用户可以轻松地批准推文。

以下是三个模板,按顺序排列:

// 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 应用程序连接到 Twitter 流 API。 但是,它还没有完全准备好生产。 您还应该考虑其他一些事项:

  • 您可能需要配置 Laravel 用来监控队列侦听器 的 Supervisor ,以监控您的 Artisan 命令并在失败时重新启动它。
  • 您需要在部署过程中处理对 Supervisor 的调用。
  • 您的搜索词可能会发生变化,Phiehose 提供了一种方法 可以在不中断脚本的情况下更新它们。