Weave 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

Relay Point Bundle Laravel Package

keirontw/relay-point-bundle

A PHP bundle for adding relay point and pickup location support to your application. It provides configuration and service integration for shipping, checkout, and delivery workflows, making it easier to manage selectable parcel pickup points.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a pure Symfony bundle, not a Laravel package. There is no RelayPointServiceProvider, no auto-discovered config, no facade, and no Blade/Twig views shipped in a Laravel-compatible layout. Before installing, decide which of these you actually want:

  1. Symfony-dominant — a Symfony app (or a Symfony microservice) owns the picker, Laravel redirects/iframes to it.
  2. Laravel adapter — you wire the bundle's services manually inside a Laravel service provider. Feasible, because Laravel already ships symfony/http-foundation and can pull symfony/http-client, but you own the glue.

Minimal steps for the adapter path:

composer require keirontw/relay-point-bundle
  • Read the README config reference first, then RelayPointProviderInterface — that interface is the only stable extension contract you should build against.
  • Copy the bundle's config tree into config/relay-point.php yourself. Laravel will not import the Symfony Configuration class, so you are transcribing keys by hand.
  • In AppServiceProvider::register(), bind a RelayPointProviderInterface instance per carrier and tag them, then construct the bundle's selector/registry service with that tagged iterator.
  • Bridge the session: the bundle reads/writes a Symfony session; Laravel's Illuminate\Session\Store is not a SessionInterface. Either wrap it in an adapter or override the storage service with your own implementation of whatever the bundle type-hints.
  • First use case that ships value fastest: a standalone relay-point picker page (one route, one Livewire/Blade component) that stores the chosen point in session under the bundle's key, then reads it back at checkout.

Implementation Patterns

Config translation, not config publishing. Keep a single config/relay-point.php that mirrors the bundle's tree 1:1, and add a config('relay-point.*') read in your provider. Write one test that asserts every key you expect exists, because Symfony's config-tree validation will not run for you.

Carrier registration via tags. Auto-discovery of RelayPointProviderInterface is a Symfony compiler-pass feature. In Laravel, do it explicitly:

$this->app->tag([MondialRelayProvider::class, ChronopostProvider::class], 'relay_point.providers');
$this->app->singleton(RelayPointRegistry::class, fn ($app) => new RelayPointRegistry(...$app->tagged('relay_point.providers')));

Only register carriers you have credentials and contracts for — instantiating a dozen providers at boot is wasted work.

Geocoder as a swappable binding. The pluggable geocoding is the most portable part of the package. Bind one geocoder interface implementation and switch by env: Addok/Nominatim for self-hosted or dev, Google Maps for production accuracy, Photon as a middle ground. Wrap the chosen geocoder in a caching decorator (Laravel Cache::remember keyed on normalized address) — geocoding is the slowest and most rate-limited call in the flow.

Selection storage as a first-class abstraction. Do not scatter session()->get('relay_point') through controllers. Introduce RelayPointSelection (a small value object: carrier, id, label, address, lat/lng) and one SelectionStore that owns read/write/forget. When/if the bundle's session format changes, you patch one class.

Checkout listener. The optional checkout_listener.enabled + event_class hook is a Symfony event-dispatcher pattern. In Laravel, skip it and use a native listener on your own OrderPlacing event that reads SelectionStore and writes the relay point onto the order. You get the same outcome with less indirection and normal Laravel event fakes in tests.

Widget rendering. The Stimulus widget is the genuinely reusable asset — Stimulus works fine under Laravel Vite. The Twig templates are not. Two options: install twigbridge and render the bundle's Twig blocks from Blade, or (usually better) treat the Twig markup as a reference implementation and rebuild the ~3 templates in Blade with the same data-* controller attributes. The CSS variable theming contract (--relay-point-*) survives either way — keep those variable names in your own stylesheet so theming stays aligned with docs.

AssetMapper registration is a no-op for you. Guard your boot code so the absence of symfony/asset-mapper doesn't throw; expect to import the JS via vite.config.js instead.

Testing. Use Symfony's MockHttpClient for carrier and geocoder responses — Laravel's Http::fake() only intercepts the Laravel HTTP client and will not touch Symfony HttpClient calls made inside the bundle. Assert on your SelectionStore and on RelayPointSelection hydration rather than on bundle internals.

Gotchas and Tips

  • Vendor/repo mismatch. The install line targets keirontw/relay-point-bundle while the README lives under BastienMesnil/relay-point-bundle. Confirm on Packagist which namespace is the maintained one before pinning; a mismatch here is a supply-chain question, not a typo.
  • No Laravel auto-discovery. Composer's extra.laravel block is absent, so nothing registers itself. Every service the bundle expects must be bound by you, and the failure mode is a container "unresolvable dependency" deep in a carrier provider rather than a clear "package not installed" error.
  • Silent config typos. Symfony validates its config tree and fails loudly; your transcribed array does not. A misspelled checkout_listener.enable is a silently disabled feature. Add an assertion test.
  • Session format is undocumented contract. The bundle "assumes no Order/cart model" — good — but the session payload shape is the real coupling. Never render it raw into your checkout; always hydrate through your value object so a patch release can't leak internals into your order record.
  • Carrier APIs are contractual and asymmetrical. Mondial Relay, Colissimo, DPD, DHL etc. differ in auth (API key vs. customer ID vs. OAuth), sandbox availability, and whether a relay-point lookup requires a pre-created shipment. Don't plan a uniform "list all carriers" UI until you've smoke-tested each one you intend to ship; some will need partner approval you don't have yet.
  • Nominatim's usage policy forbids heavy automated use and requires a valid User-Agent and attribution. Fine for dev, not for a checkout flow at volume — budget for Google Maps or a self-hosted Addok.
  • Rate limits and retries. Relay-point lookups are bursty (user drags the map). Debounce in the widget, and add a short-TTL cache (hours, not seconds) keyed on carrier + postcode + radius.
  • Coordinate systems. Geocoders return WGS-84; some carrier APIs expect a different projection for distance sorting. Verify radius filtering against a known address pair per carrier.
  • Version pin tightly. At 1.0.0 with a hand-written integration layer, use "keirontw/relay-point-bundle": "1.0.*" and re-run your container/config assertions on every bump — you have no Symfony deprecation layer to warn you.
  • Extension points worth using: RelayPointProviderInterface (add a carrier the bundle doesn't cover, or stub one in tests), the geocoder interface (inject a cached/fake implementation), and Twig block overrides only if you go the twigbridge route. Everything else — config tree, asset registration, event listener — is Symfony-shaped and should be replaced with idiomatic Laravel in the adapter.
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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums