oleksyuk/apaleo-bundle
A Symfony bundle for integrating the Apaleo hospitality API into PHP applications. It provides bundle configuration, service container wiring, and convenient clients/services to connect your app with Apaleo property, booking, and rate data.
This is a Symfony bundle, not a Laravel package — the first decision for a Laravel developer is whether to install it at all. v0.1.0 requires symfony/* 8.x, which conflicts with the Symfony 7.x components shipped by current Laravel releases, so the bundle itself is effectively off-limits inside a Laravel app. Use the underlying SDK, maks-oleksyuk/apaleo-php ^0.1, and replicate the bundle's wiring by hand.
composer require maks-oleksyuk/apaleo-php:^0.1 (pin the minor — this is pre-1.0).client_id/client_secret, optional base_uri for the sandbox, and the token_cache PSR-6 pool.config/apaleo.php reading APALEO_CLIENT_ID, APALEO_CLIENT_SECRET, APALEO_BASE_URI, and bind an ApaleoClient singleton in AppServiceProvider.GET (e.g. list properties) and dumps the token expiry — that confirms credentials, base URI, and cache all work before you build anything on top.Singleton client, config-driven. Resolve ApaleoClient from the container everywhere; never construct it in a controller. Keep credentials in config/apaleo.php backed by env so config:cache works and sandbox/production swap cleanly.
Mirror the shared token cache. The bundle's key behaviour is caching the client-credentials token in cache.app (or any PSR-6 pool). In Laravel, adapt a store with Symfony\Component\Cache\Adapter\Psr6Cache (or cache/psr6-adapter) and point it at Redis when you run more than one app server — otherwise every PHP-FPM worker does its own token handshake. Verify TTL behaviour: a token cached for longer than its expires_in produces 401s that look like bad credentials.
Bring your own PSR-18 client. The SDK needs a PSR-18 client plus PSR-17 factories. Laravel's Http facade is not PSR-18; wire symfony/http-client or Guzzle explicitly. Configure the same defaults the bundle ships: 10 s timeout, retries on 5xx and transport errors for GET/HEAD only.
Treat rate limits as a queue concern. 429 surfaces as ApaleoRateLimitException rather than sleeping — that is the right design, and it means your controllers should not be calling apaleo synchronously. Put calls in queued jobs, catch the exception, and release with jittered backoff ($this->release($backoff) or a RateLimited job middleware). Add $tries/$retryUntil so a sustained 429 doesn't silently drop work.
Writes need idempotency. Because POST/PUT/PATCH are not retried by the client, a timeout mid-write is ambiguous. Either supply idempotency keys where apaleo supports them, or persist a local "attempt" record and reconcile before resubmitting.
Decorator for observability. Wrap the PSR-18 client in a small logging/metrics decorator (request, status, duration, correlation id). The Symfony profiler integration advertised in the release notes has no Laravel equivalent, so this decorator replaces it.
Testing. Bind a fake PSR-18 client (or an HttpClientInterface mock) in the test container and assert on the outgoing request rather than hitting the sandbox.
array driver in tests is fine, in production it is not). Confirm you're on Redis/database, not array.POST will not be retried. If your integration creates reservations or folios, assume every write can fail exactly once mid-flight and design for it.base_uri defaults to production. Set APALEO_BASE_URI explicitly in .env.example and every non-production environment; a missing sandbox URI means test data lands in the real tenant.^0.1 on both SDK and bundle means minor bumps can break signatures. Pin exact versions in composer.json, read the changelog before upgrading, and keep the SDK behind your own thin gateway class so a breaking change is one file, not fifty call sites.How can I help you explore Laravel packages today?