spatie/laravel-twitter-streaming-api
Laravel package to consume Twitter’s Streaming API. Easily listen to public streams for keywords/hashtags or user actions with a fluent API and callbacks, then start a long-running listener (e.g., via an Artisan command) to process incoming tweets in real time.
Installation:
composer require spatie/laravel-twitter-streaming-api
php artisan vendor:publish --provider="Spatie\TwitterStreamingApi\TwitterStreamingApiServiceProvider"
config/twitter-streaming-api.php) with default credentials (update with your Twitter API keys).First Use Case: Listen for tweets containing a specific hashtag and log them:
use Spatie\TwitterStreamingApi\Facades\TwitterStreamingApi;
TwitterStreamingApi::publicStream()
->whenHears('#laravel', function (array $tweet) {
\Log::info("New tweet: " . $tweet['text']);
})
->startListening();
Key Config:
api_key, api_secret_key, access_token, and access_token_secret in .env or config file.Stream Types:
TwitterStreamingApi::publicStream()
->whenHears(['#php', '#laravel'], function ($tweet) { ... })
->startListening();
TwitterStreamingApi::userStream('target_user_screen_name')
->whenLikes(function ($tweet) { ... })
->startListening();
TwitterStreamingApi::filteredStream()
->track(['#laravel', '#coding'])
->whenHears('#spam', function () { return false; }) // Ignore spam
->startListening();
Event Callbacks:
->whenHears('#job', function ($tweet) {
// Process tweet (e.g., save to DB, trigger webhook)
$this->dispatch(new ProcessTweet($tweet));
})
->whenFollows(function ($user) {
// Handle follow events
});
$buffer = [];
TwitterStreamingApi::publicStream()
->whenHears('#news', function ($tweet) use (&$buffer) {
$buffer[] = $tweet;
if (count($buffer) >= 100) {
$this->processBuffer($buffer);
$buffer = [];
}
});
Artisan Commands:
php artisan twitter:stream --hashtag="#laravel" --action="log"
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Spatie\TwitterStreamingApi\Facades\TwitterStreamingApi;
class StreamHashtags extends Command
{
protected $signature = 'twitter:stream {--hashtag=*}';
public function handle()
{
TwitterStreamingApi::publicStream()
->whenHears($this->option('hashtag'), function ($tweet) {
\Log::info($tweet['text']);
})
->startListening();
}
}
Integration with Queues:
->whenHears('#alert', function ($tweet) {
dispatch(new ProcessTweetJob($tweet));
});
Database Storage:
tweets) with a model:
->whenHears('#save', function ($tweet) {
Tweet::create([
'user_id' => $tweet['user']['id'],
'text' => $tweet['text'],
'created_at' => now(),
]);
});
Rate Limits:
Connection Drops:
->reconnect() or wrap in a retry loop:
while (true) {
try {
TwitterStreamingApi::publicStream()->whenHears(...)->startListening();
} catch (\Exception $e) {
\Log::error("Stream failed: " . $e->getMessage());
sleep(10); // Wait before reconnecting
}
}
Memory Leaks:
Authentication Issues:
php artisan twitter:auth:validate
.env variables and never hardcode keys.Timeouts:
max_execution_time may kill long-running streams.set_time_limit(0); // Infinite timeout (use cautiously)
Logging:
'debug' => env('TWITTER_STREAMING_DEBUG', false),
->whenHears('#debug', function ($tweet) {
\Log::debug('Raw tweet:', $tweet);
});
Testing Locally:
$this->mock(TwitterStreamingApi::class)->shouldReceive('publicStream')
->andReturnSelf()
->shouldReceive('whenHears')
->andReturnSelf()
->shouldReceive('startListening')
->once();
Common Errors:
420 Error: Too many requests. Implement backoff.401 Unauthorized: Invalid credentials. Double-check .env.403 Forbidden: IP/access restrictions. Use Twitter’s API status page.Filter Efficiency:
->track(['#laravel', '#php'])
->whenHears('#spam', function () { return false; }) // Exclude spam
->whenFollows(function ($user) {
if ($user['followers_count'] > 1000) { ... } // Ignore low-engagement users
});
Webhooks:
->whenHears('#webhook', function ($tweet) {
Http::post('https://your-service.com/webhook', ['tweet' => $tweet]);
});
Environment-Specific Config:
config/caching to load different keys per environment:
'keys' => [
'local' => ['api_key' => 'local_key'],
'production' => ['api_key' => env('TWITTER_API_KEY')],
],
Performance:
Extending the Package:
Spatie\TwitterStreamingApi\StreamBuilder:
class CustomStream extends StreamBuilder
{
public function customAction($callback)
{
$this->actions[] = ['custom', $callback];
return $this;
}
}
$this->app->bind('custom.stream', function () {
return new CustomStream();
});
How can I help you explore Laravel packages today?