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

Rest Bundle Laravel Package

baikal/rest-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to your composer.json:

    composer require baikal/rest-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Baikal\RestBundle\BaikalRestBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default config:

    php bin/console baikal:rest:install
    

    Update config/packages/baikal_rest.yaml with your OAuth credentials (e.g., from Baïkal CalDAV server).

  3. First Use Case Create a basic REST controller to interact with Baïkal:

    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\Routing\Annotation\Route;
    use Baikal\RestBundle\Client\BaikalClient;
    
    class BaikalController
    {
        private $baikalClient;
    
        public function __construct(BaikalClient $baikalClient)
        {
            $this->baikalClient = $baikalClient;
        }
    
        #[Route('/events', methods: ['GET'])]
        public function listEvents(): JsonResponse
        {
            $events = $this->baikalClient->getEvents();
            return new JsonResponse($events);
        }
    }
    

    Test with:

    php bin/console server:run
    

    Access http://localhost:8000/events.


Implementation Patterns

Common Workflows

  1. Authentication Use the BaikalClient with injected OAuth credentials:

    $client = $this->baikalClient->authenticate(
        $accessToken,
        $refreshToken // Optional
    );
    
  2. CRUD Operations Leverage the bundle’s methods for common CalDAV operations:

    // Create
    $event = $this->baikalClient->createEvent([
        'summary' => 'Team Meeting',
        'dtstart' => '20231015T100000Z',
        'dtend' => '20231015T110000Z',
    ]);
    
    // Read
    $event = $this->baikalClient->getEvent($eventId);
    
    // Update
    $this->baikalClient->updateEvent($eventId, ['summary' => 'Updated Meeting']);
    
    // Delete
    $this->baikalClient->deleteEvent($eventId);
    
  3. Event Subscriptions Use Symfony’s Messenger component to queue Baïkal API calls:

    use Baikal\RestBundle\Message\SyncEventsMessage;
    
    $this->messageBus->dispatch(
        new SyncEventsMessage($userId, $sinceDate)
    );
    
  4. Webhook Integration Handle Baïkal webhooks via a controller:

    #[Route('/baikal/webhook', methods: ['POST'])]
    public function handleWebhook(Request $request): Response
    {
        $payload = json_decode($request->getContent(), true);
        $this->baikalClient->processWebhook($payload);
        return new Response('OK');
    }
    

Integration Tips

  • CORS Configuration Extend nelmio_cors config to allow Baïkal API domains:

    # config/packages/nelmio_cors.yaml
    paths:
        '^/api/baikal/':
            allow_origin: ['*']
            allow_methods: ['GET', 'POST', 'PUT', 'DELETE']
            allow_headers: ['Authorization', 'Content-Type']
    
  • Dependency Injection Bind custom Baïkal clients per environment:

    # config/services.yaml
    services:
        Baikal\RestBundle\Client\BaikalClient:
            arguments:
                $baseUri: '%env(BAIKAL_API_URL)%'
                $clientId: '%env(BAIKAL_CLIENT_ID)%'
                $clientSecret: '%env(BAIKAL_CLIENT_SECRET)%'
    
  • Error Handling Create a global exception listener for Baïkal API errors:

    use Baikal\RestBundle\Exception\BaikalApiException;
    
    class BaikalExceptionListener
    {
        public function onKernelException(GetResponseForExceptionEvent $event)
        {
            if ($event->getThrowable() instanceof BaikalApiException) {
                $event->setResponse(new JsonResponse([
                    'error' => 'Baïkal API',
                    'message' => $event->getThrowable()->getMessage(),
                ], 400));
            }
        }
    }
    

Gotchas and Tips

Pitfalls

  1. OAuth Token Management

    • Issue: Tokens expire silently, causing 401 Unauthorized errors.
    • Fix: Implement token refresh logic in a service:
      if ($this->baikalClient->isTokenExpired()) {
          $this->baikalClient->refreshToken($refreshToken);
      }
      
  2. Rate Limiting

    • Issue: Baïkal may throttle requests if not handled gracefully.
    • Fix: Use Symfony’s HttpClient with retry middleware:
      $client = HttpClient::create([
          'base_uri' => $baseUri,
          'headers' => ['Authorization' => 'Bearer ' . $accessToken],
      ])->withOptions([
          'retry_on_status' => [429, 503],
      ]);
      
  3. Time Zone Mismatches

    • Issue: Events may appear misaligned due to time zone differences.
    • Fix: Normalize dates to UTC before sending/receiving:
      $dtstart = (new \DateTime('2023-10-15 10:00:00', new \DateTimeZone('Europe/Paris')))
          ->setTimezone(new \DateTimeZone('UTC'))
          ->format('Ymd\THis\Z');
      
  4. Circular References in Serialization

    • Issue: JMS Serializer may fail on nested event objects.
    • Fix: Configure serialization groups:
      # config/packages/jms_serializer.yaml
      handlers:
          Baikal\RestBundle\Entity\Event:
              groups: [event, event_collection]
      

Debugging Tips

  • Enable API Logging Add a subscriber to log Baïkal API requests/responses:

    use Psr\Log\LoggerInterface;
    
    class BaikalLoggerSubscriber implements EventSubscriberInterface
    {
        private $logger;
    
        public function __construct(LoggerInterface $logger)
        {
            $this->logger = $logger;
        }
    
        public function onKernelRequest(GetResponseEvent $event)
        {
            if ($event->getRequest()->getPathInfo() === '/api/baikal/events') {
                $this->logger->debug('Baïkal API Request', [
                    'uri' => $event->getRequest()->getUri(),
                    'body' => $event->getRequest()->getContent(),
                ]);
            }
        }
    }
    
  • Test with Mocked Client Use PHPUnit to mock BaikalClient:

    $mockClient = $this->createMock(BaikalClient::class);
    $mockClient->method('getEvents')->willReturn([/* mock data */]);
    
    $controller = new BaikalController($mockClient);
    $response = $controller->listEvents();
    $this->assertEquals(200, $response->getStatusCode());
    

Extension Points

  1. Custom Endpoints Extend the bundle by creating a custom client:

    class CustomBaikalClient extends BaikalClient
    {
        public function getCustomEvents(array $filters): array
        {
            return $this->get('/custom-endpoint', [
                'query' => $filters,
            ]);
        }
    }
    
  2. Event Transformers Override serialization/deserialization:

    use JMS\Serializer\Context;
    
    class CustomEventTransformer implements TransformerInterface
    {
        public function transform($data, Context $context)
        {
            // Custom logic here
            return $data;
        }
    }
    
  3. Webhook Verification Add HMAC verification for webhooks:

    use Symfony\Component\HttpFoundation\Request;
    
    public function verifyWebhook(Request $request): bool
    {
        $expectedSignature = hash_hmac(
            'sha256',
            $request->getContent(),
            $this->baikalClient->getWebhookSecret()
        );
        return hash_equals($expectedSignature, $request->headers->get('X-Baikal-Signature'));
    }
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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