Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twitter Client Bundle Laravel Package

desarrolla2/twitter-client-bundle

Symfony bundle that integrates a Twitter client, providing services and configuration to call the Twitter API from your app. A lightweight wrapper to authenticate and perform common Twitter operations without wiring the client manually.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require desarrolla2/twitter-client-bundle
    

    Register the bundle in config/app.php under providers:

    Desarrolla2\TwitterClientBundle\TwitterClientServiceProvider::class,
    
  2. Environment Configuration: Add Twitter API credentials to .env:

    TWITTER_CONSUMER_KEY=your_consumer_key
    TWITTER_CONSUMER_SECRET=your_consumer_secret
    TWITTER_ACCESS_TOKEN=your_access_token
    TWITTER_ACCESS_TOKEN_SECRET=your_access_token_secret
    
  3. First Use Case: Inject the TwitterClient service into a controller or command:

    use Desarrolla2\TwitterClientBundle\TwitterClient;
    
    class TwitterController extends Controller
    {
        public function __construct(private TwitterClient $twitterClient)
        {
        }
    
        public function showTimeline()
        {
            $tweets = $this->twitterClient->getUserTimeline('laravel');
            return view('timeline', compact('tweets'));
        }
    }
    

Implementation Patterns

Dependency Injection

Leverage Laravel’s service container to bind the Twitter client:

// In AppServiceProvider@boot()
$this->app->bind(TwitterClient::class, function ($app) {
    return new TwitterClient(
        $app['config']['twitter.api_key'],
        $app['config']['twitter.api_secret'],
        $app['config']['twitter.access_token'],
        $app['config']['twitter.access_token_secret']
    );
});

Command-Line Usage

Create an Artisan command for bulk operations:

use Illuminate\Console\Command;
use Desarrolla2\TwitterClientBundle\TwitterClient;

class FetchTrendingTopics extends Command
{
    protected $signature = 'twitter:trending';
    protected $description = 'Fetch trending topics';

    public function handle(TwitterClient $twitterClient)
    {
        $topics = $twitterClient->getTrends('1'); // WOEID for worldwide
        $this->info('Trending Topics:');
        foreach ($topics as $topic) {
            $this->line($topic['name']);
        }
    }
}

Event-Driven Workflows

Extend the bundle by listening to tweet events (if supported):

// In EventServiceProvider@boot()
event(new TweetFetched($tweet));

API Response Handling

Normalize Twitter API responses into Laravel collections:

$tweets = collect($twitterClient->getUserTimeline('laravel'))
    ->map(function ($tweet) {
        return [
            'id' => $tweet->id,
            'text' => $tweet->text,
            'created_at' => $tweet->created_at,
            'user' => $tweet->user->screen_name,
        ];
    });

Rate Limit Awareness

Implement retry logic for rate-limited requests:

use Spatie\Backoff\BackableInterface;
use Spatie\Backoff\ShouldRetry;

class TwitterClient implements BackableInterface
{
    public function getUserTimeline(string $screenName): array
    {
        try {
            return $this->client->getUserTimeline($screenName);
        } catch (RateLimitExceededException $e) {
            if ($this->shouldRetry($e)) {
                $this->retry();
            }
            throw $e;
        }
    }
}

Gotchas and Tips

Pitfalls

  1. Deprecated API Version: The bundle uses Twitter API v1.1, which is deprecated. Plan to migrate to v2 or fork the bundle.

  2. Laravel-Symfony DI Conflicts: The bundle assumes Symfony’s DI container. Bind services manually:

    $this->app->singleton(TwitterClient::class, function ($app) {
        return new TwitterClient(
            $app['config']['twitter.api_key'],
            $app['config']['twitter.api_secret'],
            $app['config']['twitter.access_token'],
            $app['config']['twitter.access_token_secret']
        );
    });
    
  3. No Built-in Caching: API responses aren’t cached by default. Implement Redis caching:

    $tweets = Cache::remember("tweets_{$screenName}", now()->addHours(1), function () use ($twitterClient, $screenName) {
        return $twitterClient->getUserTimeline($screenName);
    });
    
  4. Rate Limit Headers Ignored: The bundle may not handle X-Rate-Limit-* headers. Add middleware:

    $client->getMiddleware()->push(
        Middleware::retry(
            function ($retries, RequestOptions $options, ResponseInterface $response) {
                return $response->hasHeader('x-rate-limit-remaining') &&
                       $response->getHeader('x-rate-limit-remaining')[0] == '0';
            },
            function ($retries, RequestOptions $options, ResponseInterface $response) {
                $retryAfter = $response->getHeader('x-rate-limit-reset')[0];
                return $retryAfter;
            }
        )
    );
    

Debugging Tips

  1. Enable Guzzle Debugging: Add this to your AppServiceProvider:

    $this->app->singleton(GuzzleHttp\Client::class, function () {
        $client = new GuzzleHttp\Client();
        $client->getEmitter()->addSubscriber(new \GuzzleHttp\Middleware::tap(function ($request) {
            \Log::debug('Twitter Request:', [
                'url' => (string) $request->getUri(),
                'method' => $request->getMethod(),
                'headers' => $request->getHeaders(),
            ]);
        }));
        return $client;
    });
    
  2. Mock Twitter API: Use VCR for testing:

    composer require vcrphp/vcr
    
    use VCR\VCR;
    
    VCR::configure()
        ->setMode('all')
        ->addFilter(new VCR\Filter\UrlFilter('api.twitter.com'))
        ->addFilter(new VCR\Filter\HeaderFilter('Authorization'));
    
    public function testTimeline()
    {
        VCR::turnOn();
        $tweets = $this->twitterClient->getUserTimeline('laravel');
        VCR::turnOff();
        $this->assertCount(5, $tweets);
    }
    

Extension Points

  1. Custom Endpoints: Extend the client to support unsupported endpoints:

    class ExtendedTwitterClient extends TwitterClient
    {
        public function getSpaces(string $broadcasterId)
        {
            return $this->client->request('GET', "/1.1/spaces/show.json", [
                'query' => ['broadcaster_id' => $broadcasterId],
            ]);
        }
    }
    
  2. Event Dispatching: Trigger Laravel events for tweets:

    $tweets = $this->twitterClient->getUserTimeline('laravel');
    foreach ($tweets as $tweet) {
        event(new TweetFetched($tweet));
    }
    
  3. Queue Background Jobs: Offload API calls to queues:

    FetchTweets::dispatch('laravel')->delay(now()->addMinutes(5));
    
    class FetchTweets implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable;
    
        public function handle(TwitterClient $twitterClient)
        {
            $tweets = $twitterClient->getUserTimeline($this->screenName);
            // Process tweets...
        }
    }
    

Configuration Quirks

  1. Environment Variables: Ensure .env variables are loaded in config/services.php:

    'twitter' => [
        'api_key' => env('TWITTER_CONSUMER_KEY'),
        'api_secret' => env('TWITTER_CONSUMER_SECRET'),
        'access_token' => env('TWITTER_ACCESS_TOKEN'),
        'access_token_secret' => env('TWITTER_ACCESS_TOKEN_SECRET'),
    ],
    
  2. OAuth Token Rotation: Implement token refresh logic if needed:

    if ($this->isTokenExpired()) {
        $this->refreshAccessToken();
    }
    
  3. Error Handling: Catch specific exceptions:

    try {
        $tweets = $twitterClient->getUserTimeline('nonexistent');
    } catch (TwitterException $e) {
        if ($e->getCode() === 404) {
            return response()->view('user.not_found');
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle