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

Guzzle Laravel Package

hyperf/guzzle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require hyperf/guzzle
    

    Ensure your Laravel app uses Swoole (e.g., spatie/laravel-swoole) or Hyperf for coroutine support.

  2. Basic Usage: Register the Guzzle client in Laravel’s service container (e.g., AppServiceProvider):

    use Hyperf\Guzzle\ClientFactory;
    use Illuminate\Support\ServiceProvider;
    
    public function register()
    {
        $this->app->singleton(ClientFactory::class, function ($app) {
            return new ClientFactory(config('guzzle'));
        });
    }
    
  3. First Use Case: Fetch data asynchronously in a coroutine:

    use Hyperf\Guzzle\ClientFactory;
    use Swoole\Coroutine;
    
    Coroutine::create(function () {
        $client = app(ClientFactory::class)->create();
        $response = $client->get('https://httpbin.org/get');
        $data = json_decode($response->getBody(), true);
        // Process data (e.g., store in DB, dispatch event)
    });
    
  4. Configuration: Publish the config file:

    php artisan vendor:publish --provider="Hyperf\Guzzle\GuzzleServiceProvider" --tag="config"
    

    Update config/guzzle.php for timeouts, middleware, etc.


Implementation Patterns

1. Coroutine-Based HTTP Calls

Use Swoole\Coroutine for non-blocking requests:

Coroutine::create(function () {
    $client = app(ClientFactory::class)->create();
    $response = $client->request('POST', 'https://api.example.com/webhook', [
        'json' => ['event' => 'order_created'],
    ]);
    // Handle response
});

2. Middleware Stack

Attach Guzzle middleware (e.g., retries, auth) via config:

// config/guzzle.php
'middleware' => [
    \Hyperf\Guzzle\Middleware\RetryMiddleware::class,
    \GuzzleHttp\Middleware::tap(function ($request) {
        $request = $request->withHeader('Authorization', 'Bearer ' . config('services.api.token'));
        return $request;
    }),
],

3. Parallel Requests

Execute multiple HTTP calls concurrently:

$coroutines = [];
foreach ($urls as $url) {
    $coroutines[] = Coroutine::create(function () use ($url) {
        $client = app(ClientFactory::class)->create();
        return $client->get($url);
    });
}
Coroutine::wait($coroutines); // Wait for all to complete

4. Integration with Laravel Queues

Offload async HTTP calls to Laravel queues (using Swoole workers):

use Hyperf\Guzzle\ClientFactory;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;

class AsyncApiCall implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function handle()
    {
        Coroutine::create(function () {
            $client = app(ClientFactory::class)->create();
            $response = $client->get('https://api.example.com/data');
            // Process and store results
        });
    }
}

5. Error Handling

Use Guzzle’s exception handling with coroutines:

try {
    Coroutine::create(function () {
        $client = app(ClientFactory::class)->create();
        $response = $client->get('https://api.example.com/fail');
    })->throw(); // Re-throw coroutine exceptions
} catch (\GuzzleHttp\Exception\RequestException $e) {
    report($e);
    // Retry or fallback logic
}

6. Testing Coroutines

Mock coroutines in tests (e.g., PHPUnit):

use Swoole\Coroutine;

public function testAsyncCall()
{
    Coroutine::create(function () {
        // Test coroutine logic
    });

    // Simulate coroutine completion (e.g., via events or callbacks)
}

Gotchas and Tips

Pitfalls

  1. Blocking Calls in Coroutines

    • Issue: Calling blocking functions (e.g., file_get_contents(), sleep()) inside a coroutine will freeze the entire Swoole worker.
    • Fix: Use Swoole\Coroutine::yield() or offload to a separate coroutine.
  2. Global State in Coroutines

    • Issue: Shared variables across coroutines can cause race conditions.
    • Fix: Use thread-local storage or pass data explicitly.
  3. Laravel Facade Conflicts

    • Issue: Laravel’s Http facade may not work with hyperf/guzzle directly.
    • Fix: Create a custom facade or wrapper:
      class CoroutineHttpClient {
          public static function get($url) {
              return Coroutine::create(function () use ($url) {
                  $client = app(ClientFactory::class)->create();
                  return $client->get($url);
              });
          }
      }
      
  4. Timeout Misconfiguration

    • Issue: Default timeouts may not align with coroutine execution time.
    • Fix: Configure timeouts in config/guzzle.php:
      'timeout' => 10.0, // seconds
      'connect_timeout' => 2.0,
      
  5. Database Deadlocks

    • Issue: Async HTTP calls may hold database connections open.
    • Fix: Use connection pooling (e.g., pdo_swoole) or release connections explicitly.
  6. Middleware Order

    • Issue: Middleware executed in reverse order (last added runs first).
    • Fix: Define middleware in the correct sequence in config/guzzle.php.

Debugging Tips

  1. Coroutine Leaks

    • Use Swoole\Coroutine::stats() to monitor active coroutines:
      $stats = Swoole\Coroutine::stats();
      dump($stats['running_num'], $stats['total_num']);
      
  2. Logging Coroutine IDs

    • Log coroutine UIDs for traceability:
      \Log::debug('Coroutine ID: ' . Swoole\Coroutine::getuid());
      
  3. Timeout Debugging

    • Enable Guzzle debug logging:
      $client = app(ClientFactory::class)->create([
          'debug' => true,
      ]);
      
  4. Testing Async Code

    • Use Swoole\Coroutine::wait() to simulate async completion in tests:
      $coroutine = Coroutine::create(function () {
          // Async logic
      });
      Coroutine::wait($coroutine);
      

Extension Points

  1. Custom Middleware Extend Hyperf\Guzzle\Middleware\MiddlewareInterface:

    class CustomLoggingMiddleware implements MiddlewareInterface {
        public function __invoke($request, $options, $next) {
            \Log::info('Request: ' . $request->getUri());
            return $next($request, $options);
        }
    }
    
  2. Hyperf Integration For deeper Hyperf integration, use Hyperf\HttpClient:

    use Hyperf\HttpClient\Client;
    
    $client = new Client();
    $response = $client->get('https://api.example.com');
    
  3. Event-Driven Workflows Combine with Laravel events:

    Coroutine::create(function () {
        $client = app(ClientFactory::class)->create();
        $response = $client->get('https://api.example.com/events');
        event(new ApiEvent(json_decode($response->getBody(), true)));
    });
    
  4. Retry Strategies Customize retry logic in middleware:

    class ExponentialRetryMiddleware implements MiddlewareInterface {
        public function __invoke($request, $options, $next) {
            $retries = 0;
            $maxRetries = 3;
            $delay = 100; // ms
    
            while ($retries < $maxRetries) {
                try {
                    return $next($request, $options);
                } catch (\Exception $e) {
                    $retries++;
                    if ($retries >= $maxRetries) throw $e;
                    usleep($delay);
                    $delay *= 2;
                }
            }
        }
    }
    

Configuration Quirks

  1. Swoole Worker Limits

    • Ensure worker_num in swoole.php is sufficient for concurrent coroutines:
      'worker_num' => 4, // Adjust based on CPU cores
      
  2. PHP Settings

    • Increase max_execution_time and memory_limit for long-running coroutines:
      max_execution_time =
      
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor