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

Navitia Bundle Laravel Package

canaltp/navitia-bundle

Symfony bundle that integrates the Navitia API into your application, providing services and configuration to query public transport journey planning, schedules, and network data from Navitia coverage.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the SDK and bundle. The bundle is a thin Symfony wrapper around canaltp/navitia (the PHP SDK for the Navitia open transport API), so expect both packages in composer.json:

    composer require canaltp/navitia-bundle
    

    Check the bundle's composer.json constraints first — this is an old package (Symfony 2/3 era). On Symfony 4+ you may need to register it manually in config/bundles.php:

    return [
        // ...
        CanalTP\NavitiaBundle\NavitiaBundle::class => ['all' => true],
    ];
    
  2. Configure credentials. Navitia needs an API token and a coverage/region (e.g. fr-idf, fr-nantes). Put the token in an env var, never in committed YAML:

    # config/packages/navitia.yaml
    navitia:
        api_key: '%env(NAVITIA_TOKEN)%'
        coverage: 'fr-idf'
        # base_url if you point at a self-hosted Navitia instance
    

    The exact root key (navitia: vs canal_tp_navitia:) depends on the bundle version — run bin/console config:dump-reference navitia to confirm.

  3. Find the service to inject. Don't guess the service id. Inspect it:

    bin/console debug:container navitia
    bin/console debug:autowiring navitia
    

    In practice you'll get a pre-configured client or coverage object. Inject it into a controller or your own service.

  4. First use case: journey planning. The canonical Navitia call is a journey query between two places. Resolve coordinates (or use stop_area:XXX / place ids), then ask for itineraries:

    public function __construct(private Navitia $navitia) {}
    
    public function route(float $fromLat, float $fromLon, float $toLat, float $toLon): array
    {
        return $this->navitia->getCoverage('fr-idf')->journeys([
            'from' => sprintf('%F;%F', $fromLon, $fromLat),
            'to'   => sprintf('%F;%F', $toLon, $toLat),
        ]);
    }
    

    Wrap that in a small RouteController returning a mapped JSON payload. That single endpoint proves configuration, auth, and response parsing in one go.

Implementation Patterns

Never inject the bundle client deep into your domain. Create one adapter service (e.g. App\Transport\NavitiaGateway) that owns the client, the coverage, the error handling, and the mapping to your own DTOs. Everything else depends on your gateway interface. This makes swapping the SDK or the transport backend (self-hosted Navitia vs. SaaS) a one-file change.

Typical endpoint set to build, in priority order:

Feature Navitia concept Notes
Place / address autocomplete places Feed a search box; debounce on the frontend.
Stop area lookup stop_areas Resolve a station name to a stable stop_area:ID.
Journey planning journeys The core feature; supports datetime, forbidden_uris[], walking_speed, max_duration.
Departure board stop_points/{id}/departures Add duration (seconds) to bound the window.
Line / route browsing lines, routes Useful for a "network" page.

Cache aggressively on read, not on write. Schedule and topology data change on a slow cadence (typically daily imports). Cache places and stop_areas results for hours; cache journeys/departures for a few minutes at most, and key the cache on the normalized query (round coordinates to ~5 decimals, quantize the datetime to the minute) to avoid cache-key explosions.

$key = 'navitia.journey.' . md5(json_encode($normalizedParams));
return $this->cache->get($key, fn() => $this->gateway->journeys($normalizedParams));

Use a Symfony event listener for observability. The SDK will issue HTTP calls you can't see from your code. Decorate the client (or listen on the HTTP client's on_progress/kernel events) to record duration and status. Strip the token from any logged URL.

Test with the SDK's response shapes, not live calls. Record real Navitia JSON once, store as fixtures, and have your gateway tests feed those into the SDK's deserializer. Reserve a small set of @group integration tests for the sandbox API (the public demo token is rate-limited and shared — never use it in CI).

Config per environment: local → sandbox token + fr-idf; staging → same token, higher cache TTL; prod → your contract token. Keep the coverage as a parameter so tests can pin a small region.

Wire a profiler panel if the bundle provides one. If it registers a DataCollector, you'll see request count and payload size in the web debug toolbar — extremely useful for spotting an endpoint making six redundant calls per page load.

Gotchas and Tips

  • This package is effectively unmaintained. Zero dependents and a blank star count mean: pin it exactly in composer.json ("canaltp/navitia-bundle": "1.0.*"), verify its Symfony constraint against your version, and be prepared to drop the bundle and use canaltp/navitia directly with a single factory service. The bundle adds little beyond DI wiring — the cost of losing it is small.

  • The API token appears in URLs on some endpoints. Navitia historically accepted ?token= as a query param. If the SDK does that, your token leaks into access logs, proxies, and Sentry breadcrumbs. Prefer the Authorization header if the SDK supports it; otherwise scrub it in a Monolog processor.

  • Errors are inconsistent. You'll see 400s with a Navitia error object, 404s for unknown coverage/stop ids, and 200s with empty arrays when a query is valid but finds nothing. Treat "empty result" and "failed request" as distinct states in your gateway — returning [] for both will make debugging miserable.

  • Deeply nested responses blow up serialization. A single journey response with walking sections, disruptions, and fare data serializes to tens of kilobytes. Map to your own flat DTOs before returning JSON. Also set items_per_page / start_page deliberately; the default page size will silently truncate departure boards.

  • Datetime handling is the classic bug. Navitia returns local times with offsets and accepts YYYYMMDDTHHMMSS in local coverage time. Use DateTimeImmutable with explicit timezone conversion at the boundary; never pass a naive "now" from PHP without converting to the coverage's timezone.

  • Coordinates are lon;lat, not lat;lon. The from/to format is longitude;latitude. Getting this backwards yields plausible-looking but completely wrong routes — an easy bug to ship because it doesn't error.

  • Check autowiring aliases before assuming. If debug:autowiring navitia returns nothing, the bundle predates autowiring aliases; define your own in services.yaml:

    App\Transport\NavitiaClient:
        arguments: ['@navitia.client'] # confirm the id via debug:container
    
  • Extension points are limited. The realistic ones are (a) decorating the client service, (b) your own gateway layer, (c) a custom DataCollector if the bundle's profiler panel doesn't show what you need. Don't try to subclass bundle internals — they're not covered by a BC promise.

  • Respect rate limits. Navitia quotas are per-token and easy to exhaust with an unthrottled autocomplete. Add symfony/rate-limiter in front of the gateway and debounce on the client. A 429 from Navitia will otherwise show up as a generic 500 in your app — map it explicitly.

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