GTFS-Realtime library for PHP 8.4+ based on Google's Protocol Buffers v5.
A modern PHP implementation of the GTFS Realtime specification.
The proto definition was downloaded from gtfs.org and converted to proto3 syntax for compatibility with the latest google/protobuf PHP library.
- PHP >= 8.4
- google/protobuf ^5.34
composer require dacoto/gtfs-rt-phpuse Google\Transit\Realtime\FeedMessage;
use Google\Transit\Realtime\FeedHeader;
use Google\Transit\Realtime\FeedHeader\Incrementality;
use Google\Transit\Realtime\FeedEntity;
use Google\Transit\Realtime\TripUpdate;
use Google\Transit\Realtime\TripUpdate\StopTimeUpdate;
use Google\Transit\Realtime\TripUpdate\StopTimeEvent;
use Google\Transit\Realtime\TripDescriptor;
$feedMessage = new FeedMessage();
$header = new FeedHeader();
$header->setGtfsRealtimeVersion('2.0');
$header->setIncrementality(Incrementality::FULL_DATASET);
$header->setTimestamp(time());
$feedMessage->setHeader($header);
$entity = new FeedEntity();
$entity->setId('entity-1');
$tripDescriptor = new TripDescriptor();
$tripDescriptor->setTripId('trip-123');
$tripDescriptor->setRouteId('route-42');
$arrivalEvent = new StopTimeEvent();
$arrivalEvent->setDelay(120); // 2 minutes late
$stopTimeUpdate = new StopTimeUpdate();
$stopTimeUpdate->setStopSequence(1);
$stopTimeUpdate->setStopId('stop-A');
$stopTimeUpdate->setArrival($arrivalEvent);
$tripUpdate = new TripUpdate();
$tripUpdate->setTrip($tripDescriptor);
$tripUpdate->setStopTimeUpdate([$stopTimeUpdate]);
$entity->setTripUpdate($tripUpdate);
$feedMessage->setEntity([$entity]);
// Serialize to binary protobuf
$binaryData = $feedMessage->serializeToString();use Google\Transit\Realtime\FeedMessage;
$binaryData = file_get_contents('https://your-agency.com/gtfs-rt/tripupdates.pb');
$feedMessage = new FeedMessage();
$feedMessage->mergeFromString($binaryData);
echo "GTFS-RT version: " . $feedMessage->getHeader()->getGtfsRealtimeVersion() . PHP_EOL;
foreach ($feedMessage->getEntity() as $entity) {
if ($entity->hasTripUpdate()) {
$tripUpdate = $entity->getTripUpdate();
echo "Trip ID: " . $tripUpdate->getTrip()->getTripId() . PHP_EOL;
foreach ($tripUpdate->getStopTimeUpdate() as $stu) {
if ($stu->hasArrival()) {
echo " Stop " . $stu->getStopId() . " delay: " . $stu->getArrival()->getDelay() . "s" . PHP_EOL;
}
}
}
}See full examples in the examples/ directory.
The official GTFS Realtime proto uses proto2 syntax. This library converts it to proto3 to be compatible with the latest google/protobuf PHP library. The key changes are:
- Changed
syntax = "proto2"tosyntax = "proto3" - Removed all
optionalandrequiredfield labels (all fields are optional in proto3) - Removed all
extensionsranges (not supported in proto3) - Removed all explicit
[default = ...]values - Added
UNKNOWN_CAUSE = 0,NO_SERVICE = 0, andUNKNOWN_SEVERITY = 0as first enum values (proto3 requires first value to be 0) - Added PHP namespace options:
php_namespaceandphp_metadata_namespace
composer install
vendor/bin/phpunitThe PHP classes in src/ are generated automatically from gtfs-realtime.proto using protoc.
Every time composer.json or gtfs-realtime.proto is changed on main, the
Regenerate PHP Classes workflow runs automatically,
downloads the correct protoc binary, regenerates all PHP classes, and commits the result.
You can also trigger it manually from the Actions tab, optionally overriding the protoc version.
Run the generation script — it resolves the protoc version from composer.json (or composer.lock) automatically:
bash bin/generate.shOr override the protoc version explicitly:
bash bin/generate.sh --protoc-version 34.1The script:
- Reads the
google/protobufversion fromcomposer.lock(orcomposer.json) - Derives the matching
protocrelease (e.g. PHPv5.34.1→protoc v34.1) - Downloads the
protocbinary from github.com/protocolbuffers/protobuf - Regenerates all PHP classes in
src/fromgtfs-realtime.proto
MIT — See LICENSE
