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

Api Adapter Bundle Laravel Package

beyerz/api-adapter-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require beyerz/api-adapter-bundle
    

    Add the bundle to AppKernel.php last in the registerBundles() array:

    $bundles[] = new Beyerz\ApiAdapterBundle\BeyerzApiAdapterBundle();
    
  2. Configure a Client (config.yml):

    beyerz_api_adapter:
      json:
        stripe: # Client name (injected via `beyerz_api_adapter.client.stripe`)
          base_url: "https://api.stripe.com/v1"
          options:
            - "auth_key=sk_test_..."
    
  3. First Use Case: Create a Manager class (e.g., StripeManager) to encapsulate API logic:

    use Beyerz\ApiAdapterBundle\Manager\ManagerInterface;
    use Beyerz\ApiAdapterBundle\Gateway\GatewayInterface;
    
    class StripeManager implements ManagerInterface
    {
        private $gateway;
    
        public function __construct(GatewayInterface $gateway)
        {
            $this->gateway = $gateway;
        }
    
        public function createCustomer(array $data)
        {
            return $this->gateway->post('/customers', $data);
        }
    }
    

    Register the manager as a service in services.yml:

    services:
        stripe.manager:
            class: AppBundle\Manager\StripeManager
            arguments: ["@beyerz_api_adapter.client.stripe"]
    

Implementation Patterns

Core Workflow

  1. Define a Manager:

    • Extend ManagerInterface or implement it directly.
    • Inject the GatewayInterface (auto-wired via beyerz_api_adapter.client.{name}).
    • Use the gateway to make HTTP calls (e.g., get(), post(), put()).
  2. Data Handling:

    • Use JMSSerializer (bundled dependency) to serialize/deserialize responses.
    • Define data classes (e.g., StripeCustomer) with @Serializer\SerializedName annotations for API response mapping:
      use JMS\Serializer\Annotation as Serializer;
      
      class StripeCustomer
      {
          /** @Serializer\SerializedName("id") */
          public $id;
      
          /** @Serializer\SerializedName("email") */
          public $email;
      }
      
    • Pass the class to the gateway to auto-populate:
      $customer = $this->gateway->get('/customers/1', StripeCustomer::class);
      
  3. Error Handling:

    • Wrap gateway calls in try-catch blocks to handle HTTP/JSON errors:
      try {
          $response = $this->gateway->post('/charges', $data);
      } catch (\RuntimeException $e) {
          // Log or rethrow
      }
      
  4. Reusable Logic:

    • Centralize common API operations (e.g., pagination, retries) in the manager.
    • Example: Add a withRetry() helper to the manager:
      public function withRetry(callable $callback, int $retries = 3)
      {
          $attempts = 0;
          while ($attempts < $retries) {
              try {
                  return $callback();
              } catch (\Exception $e) {
                  $attempts++;
                  if ($attempts >= $retries) throw $e;
                  sleep(2 ** $attempts); // Exponential backoff
              }
          }
      }
      
  5. Integration with Symfony:

    • Use dependency injection to pass managers to controllers/services:
      class StripeController extends Controller
      {
          public function createCustomerAction(Request $request, StripeManager $manager)
          {
              $data = json_decode($request->getContent(), true);
              return new JsonResponse($manager->createCustomer($data));
          }
      }
      

Gotchas and Tips

Pitfalls

  1. Bundle Ordering:

    • The bundle must be loaded last in AppKernel to avoid autoloading conflicts with other bundles that might depend on it.
  2. JMSSerializer Dependencies:

    • Ensure jms/serializer-bundle is installed (composer require jms/serializer-bundle).
    • If using Symfony 4/5, manually register the bundle in config/bundles.php:
      return [
          // ...
          JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
      ];
      
  3. Gateway Initialization:

    • The gateway is lazy-loaded via the container. Avoid instantiating it directly; always use dependency injection (@beyerz_api_adapter.client.{name}).
  4. Response Validation:

    • The bundle does not validate API responses by default. Manually check for errors:
      $response = $this->gateway->post('/charges', $data);
      if ($response->getStatusCode() !== 200) {
          throw new \RuntimeException($response->getContent());
      }
      
  5. Deprecated Symfony2:

Debugging Tips

  1. Enable Debug Mode:

    • Set beyerz_api_adapter.debug: true in config to log raw API responses:
      beyerz_api_adapter:
          debug: true
          json:
              stripe:
                  base_url: "https://api.stripe.com/v1"
      
  2. Gateway Logs:

    • Check Symfony’s profiler (/_profiler) for HTTP request/response details if debug mode is enabled.
  3. Serializer Issues:

    • If deserialization fails, verify:
      • The data class has correct @Serializer\SerializedName annotations.
      • The API response matches the expected structure (use var_dump($response->getContent()) to inspect).
  4. Caching Responses:

    • Implement a decorator around the gateway to cache responses (e.g., using Symfony’s CacheInterface):
      class CachedGateway implements GatewayInterface
      {
          private $gateway;
          private $cache;
      
          public function __construct(GatewayInterface $gateway, CacheInterface $cache)
          {
              $this->gateway = $gateway;
              $this->cache = $cache;
          }
      
          public function get($uri, $class = null)
          {
              $cacheKey = md5($uri);
              $response = $this->cache->get($cacheKey);
              if ($response) return $response;
      
              $response = $this->gateway->get($uri, $class);
              $this->cache->set($cacheKey, $response, 300); // Cache for 5 mins
              return $response;
          }
      }
      

Extension Points

  1. Custom Gateways:

    • Extend Beyerz\ApiAdapterBundle\Gateway\Gateway to add custom logic (e.g., signing requests):
      class CustomGateway extends Gateway
      {
          protected function prepareRequest(Request $request)
          {
              $request->headers->set('X-Custom-Header', 'value');
              return parent::prepareRequest($request);
          }
      }
      
    • Register the custom gateway as a service and override the default:
      services:
          beyerz_api_adapter.client.stripe:
              class: AppBundle\Gateway\CustomGateway
              arguments: ["@beyerz_api_adapter.client.stripe.inner"]
      
  2. Event Dispatching:

    • Dispatch events before/after API calls using Symfony’s EventDispatcherInterface:
      class StripeManager
      {
          private $gateway;
          private $dispatcher;
      
          public function __construct(GatewayInterface $gateway, EventDispatcherInterface $dispatcher)
          {
              $this->gateway = $gateway;
              $this->dispatcher = $dispatcher;
          }
      
          public function createCustomer(array $data)
          {
              $this->dispatcher->dispatch(new PreApiEvent('stripe.customer.create', $data));
              $response = $this->gateway->post('/customers', $data);
              $this->dispatcher->dispatch(new PostApiEvent('stripe.customer.create', $response));
              return $response;
          }
      }
      
  3. Middleware Support:

    • Add middleware (e.g., retry, logging) by extending the gateway’s sendRequest() method:
      class MiddlewareGateway extends Gateway
      {
          public function sendRequest(Request $request)
          {
              // Add middleware logic here
              return parent::sendRequest($request);
          }
      }
      
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.
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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