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 Factory Laravel Package

graham-campbell/guzzle-factory

Simple factory for creating Guzzle HTTP clients with sensible defaults. Configure options like base_uri and get a ready-to-use client in one call. Supports PHP 7.4–8.5 and integrates cleanly into modern PHP projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require graham-campbell/guzzle-factory
    

    Add to composer.json if using Laravel’s autoloader or register the service provider in config/app.php if needed (though this package is framework-agnostic).

  2. First Use Case: Create a client with a base URI in a Laravel service or controller:

    use GrahamCampbell\GuzzleFactory\GuzzleFactory;
    
    $client = GuzzleFactory::make(['base_uri' => 'https://api.example.com']);
    
  3. Where to Look First:

    • README.md: For basic usage and installation.
    • Changelog: To verify compatibility with your PHP version (e.g., PHP 8.5 support in v7.0.3).
    • Source Code: src/GuzzleFactory.php for method signatures and defaults (e.g., retry logic, TLS settings).

Implementation Patterns

Usage Patterns

  1. Centralized Client Creation: Define clients in a dedicated service class (e.g., app/Services/HttpClientService.php) to avoid repetition:

    class HttpClientService
    {
        public function createPaymentClient(): ClientInterface
        {
            return GuzzleFactory::make([
                'base_uri' => config('services.stripe.base_uri'),
                'timeout'  => 30,
                'headers'  => ['Authorization' => 'Bearer ' . config('services.stripe.key')],
            ]);
        }
    }
    
  2. Dependency Injection in Laravel: Bind the factory to the service container for easy access:

    // In a service provider (e.g., AppServiceProvider)
    $this->app->singleton('guzzle.factory', function () {
        return new GuzzleFactory();
    });
    

    Then inject it into controllers/services:

    public function __construct(private GuzzleFactory $guzzleFactory) {}
    
  3. Dynamic Configuration: Use Laravel’s config or environment variables to customize clients:

    $client = GuzzleFactory::make([
        'base_uri' => env('API_BASE_URL'),
        'timeout'  => env('API_TIMEOUT', 10),
        'retries'  => [
            'total' => env('API_RETRIES', 3),
            'backoff' => 200, // ms
        ],
    ]);
    
  4. Handler Stack Customization: For advanced use cases (e.g., custom middleware), use the getHandlerStack method:

    $stack = GuzzleFactory::getHandlerStack();
    $stack->push(Middleware::tap(...));
    $client = new Client(['handler' => $stack]);
    
  5. Retry Policies: Leverage built-in retry logic for transient failures (e.g., 429, 5xx):

    $client = GuzzleFactory::make([
        'base_uri' => 'https://api.example.com',
        'retry' => [
            'enabled' => true,
            'total'   => 5,
            'backoff' => 300, // ms
            'except'  => [401, 403], // Skip retries for auth errors
        ],
    ]);
    
  6. Testing: Mock the factory in unit tests to isolate HTTP logic:

    $mockClient = Mockery::mock(ClientInterface::class);
    $mockFactory = Mockery::mock(GuzzleFactory::class);
    $mockFactory->shouldReceive('make')->andReturn($mockClient);
    
    $this->app->instance(GuzzleFactory::class, $mockFactory);
    

Workflows

  1. API Integration Workflow:

    • Step 1: Define client config in config/services.php:
      'stripe' => [
          'base_uri' => 'https://api.stripe.com/v1',
          'timeout'  => 30,
      ],
      
    • Step 2: Create a service class to encapsulate API calls:
      class StripeService
      {
          public function __construct(private GuzzleFactory $guzzleFactory) {}
      
          public function createCustomer(array $data): array
          {
              $client = $this->guzzleFactory->make(config('services.stripe'));
              $response = $client->post('/customers', ['json' => $data]);
              return json_decode($response->getBody(), true);
          }
      }
      
    • Step 3: Inject the service into controllers or commands.
  2. Modular Architecture: Use the factory in Laravel packages or modules to ensure consistency across teams:

    // In a package's service provider
    $this->app->bind('package.http-client', function () {
        return GuzzleFactory::make([
            'base_uri' => 'https://package-api.example.com',
            'timeout'  => 15,
        ]);
    });
    
  3. Background Jobs: Pass clients to Laravel jobs for async processing:

    class ProcessPaymentJob implements ShouldQueue
    {
        public function __construct(private GuzzleFactory $guzzleFactory) {}
    
        public function handle()
        {
            $client = $guzzleFactory->make(config('services.payment-gateway'));
            // Process payment...
        }
    }
    

Integration Tips

  1. Laravel Configuration: Store default options in config/services.php and override them per client:

    'guzzle' => [
        'defaults' => [
            'timeout'  => 10,
            'retries'  => ['total' => 3],
        ],
    ],
    

    Then merge them in your factory call:

    $client = GuzzleFactory::make(array_merge(
        config('guzzle.defaults'),
        ['base_uri' => 'https://custom-api.example.com']
    ));
    
  2. Environment-Specific Configs: Use Laravel’s env() or .env files to switch between dev/staging/prod:

    $client = GuzzleFactory::make([
        'base_uri' => env('API_URL', 'https://api.example.com'),
        'debug'    => app()->environment('local'),
    ]);
    
  3. Middleware Integration: Add custom middleware to the handler stack for logging, auth, or transformation:

    $stack = GuzzleFactory::getHandlerStack();
    $stack->push(
        Middleware::tap(function (RequestOptions $options) {
            $options['headers']['X-Custom-Header'] = 'value';
        })
    );
    $client = new Client(['handler' => $stack]);
    
  4. Caching Clients: For performance, cache clients in Laravel’s cache or use a singleton pattern:

    $client = Cache::remember('stripe_client', now()->addHours(1), function () {
        return GuzzleFactory::make(config('services.stripe'));
    });
    

Gotchas and Tips

Pitfalls

  1. TLS Version Enforcement:

    • The package enforces TLS 1.2+ by default (since v7.0). If your server or API requires an older TLS version, you’ll need to:
      • Upgrade your server’s TLS configuration.
      • Use a custom handler stack to override this (not recommended for security).
    • Debugging: Check for cURL error 35 (SSL connect errors) or Guzzle\Exception\ConnectException in logs.
  2. Retry Logic Quirks:

    • Retries are enabled by default for status codes 429, 5xx, and customizable 4xx codes (see retry.except).
    • Gotcha: Retries may not work as expected if the base_uri is dynamic (e.g., load-balanced endpoints). Ensure the URI is stable during retries.
    • Tip: Disable retries for idempotent operations (e.g., GET requests) to avoid unnecessary calls:
      'retry' => ['enabled' => false],
      
  3. Handler Stack Overrides:

    • If you manually create a handler stack (e.g., for middleware), ensure it includes the factory’s default middleware:
      $stack = GuzzleFactory::getHandlerStack();
      // Add custom middleware...
      $client = new Client(['handler' => $stack]);
      
    • Pitfall: Skipping this may break retry logic or other defaults.
  4. PHP Version Mismatches:

    • The package drops support for PHP <7.4. If you’re using an older version, you’ll need to:
      • Downgrade to v5.x (last version supporting PHP 7.0–7.4).
      • Or upgrade PHP (recommended for security and performance).
    • Debugging: Look for FatalError or RuntimeException during installation/composer update.
  5. Base URI Validation:

    • The base_uri must be a valid URL (e.g., https://example.com). Relative paths or malformed URIs will throw exceptions.
    • Tip: Validate URIs early in your config:
      $baseUri = filter_var(config('services
      
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport