omnisense / omnitravel
Omnitravel: going from A to B under any PHP host, whoever keeps the data - a stop's or a station's next departures and arrivals in real time (delays, platforms, gates, cancellations), journeys across modes, where vehicles are, the network's stops and lines with their colours. One family for urban tr
Requires
- php: >=8.2
- ext-mbstring: *
- omnisense/contracts: ^1.0@dev
- symfony/http-client-contracts: ^3.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- symfony/http-client: ^6.4|^7.0|^8.0
Suggests
- omnisense/omnibridge: The host contracts; omnibridge/symfony and omnibridge/laravel wire omnitravel into their host when a site needs it
- omnitravel/gtfs: Any network that publishes GTFS: its feed imported into a store (SQLite or MySQL), stops near a point, departures, lines and their stops, real time from GTFS-Realtime (trip updates, vehicle positions)
- omnitravel/navitia: Navitia: departures, journeys and the network of a coverage (France's networks, SNCF through api.sncf.com), with a key
- omnitravel/transitous: Transitous (MOTIS): journeys and departures across the open feeds it gathers, worldwide, no key
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-10 00:35:31 UTC
README
Going from A to B under any PHP host, whoever keeps the data: one family for urban transit, trains and planes, in four contracts.
| Contract | What it answers |
|---|---|
TimetablesInterface |
a stop's or a station's next departures and arrivals, in real time where the provider knows it: the expected time and the delay, the platform or the gate, cancellations |
ItinerariesInterface |
journeys from A to B across modes: their legs on foot and on board, the lines, the changes |
TrackingInterface |
where vehicles are: buses and trains from a real-time feed, aircraft from a tracking network |
NetworkInterface |
a network's places and lines: a stop, the stops near a point, a search by name, the lines with their colours, a line's stops in order, the operators |
| Provider | Contracts | Key |
|---|---|---|
| omnitravel/gtfs | timetables, network, tracking - any network that publishes GTFS, imported into a store (SQLite or MySQL), with GTFS-Realtime | none |
| omnitravel/transitous | itineraries, timetables, network (no lines list) - the community-run MOTIS 2 server over the world's open feeds | none (a User-Agent) |
| omnitravel/navitia | timetables, itineraries, network - a Navitia coverage, SNCF's through api.sncf.com | a token |
Planned, named in the family's plan: opensky (aircraft positions), aviationstack or
flightaware (flights at an airport), deutsche-bahn, ourairports (the airports themselves).
use Omnitravel\Model\{Coordinates, DepartureQuery, JourneyQuery, Place}; use Omnitravel\Registry; $travel = new Registry([new GtfsFactory($http), new TransitousFactory($http)], [ 'angers' => ['factory' => 'gtfs', 'options' => ['feed' => 'angers', 'dsn' => 'sqlite:/var/gtfs.sqlite']], 'planner' => ['factory' => 'transitous', 'options' => ['user_agent' => 'MySite/1.0 (https://example.org; travel@example.org)']], ]); $stop = $travel->network('angers')->nearby(new Coordinates(47.4712, -0.5518))[0]; $next = $travel->timetables('angers')->departures(new DepartureQuery($stop->id, limit: 5)); $ways = $travel->itineraries('planner')->journeys(new JourneyQuery(Place::at(47.4712, -0.5518), Place::at(47.4608, -0.5306)));
Usage policies
Each provider declares its usage policy as data (its policy.json: rate limits, rights,
attribution, requirements, where and when it was read), and every call through timetables(),
itineraries(), tracking() or network() is held to it: checked before, counted after,
refused with UsageLimitReachedException once a limit is reached or while the provider asks to
wait (a 429 and its Retry-After, a RateLimit field with nothing left). A site may tighten a
policy in its configuration, never loosen it:
'planner' => [ 'factory' => 'transitous', 'options' => ['user_agent' => 'MySite/1.0 (https://example.org; travel@example.org)'], 'policy' => ['rateLimits' => [['max' => 600, 'window' => 'day', 'operations' => ['journeys']]]], 'usage' => ['commercial' => false, 'open_source' => true], ],
$travel->policy('planner') gives the policy as the site runs it. Pass a shared
RateLimiterInterface as the registry's third argument when the application runs in many
processes. See docs/policies.md.
omnisense/omnitravel requires omnisense/contracts (the kernel every omnisense family builds
on: provider, factory, registry, JSON client, usage policies, testing kit) and
symfony/http-client-contracts, nothing else: no framework, no HTTP client of its own (each
provider takes the application's). It runs the same in plain PHP, a worker, Laravel or Symfony.
The manual is in docs/: installation, Symfony, models, providers, usage policies, testing, the harness, errors, writing a provider.
MIT.