fundistadi / gdal-bundle
Typed Symfony services around the GDAL command-line tools: raster/vector inspection, warping and conversion — compiled binaries only, no Python.
Package info
github.com/fundistadi/gdal-bundle
Type:symfony-bundle
pkg:composer/fundistadi/gdal-bundle
Requires
- php: >=8.4
- symfony/framework-bundle: ^7.3 || ^8.0
- symfony/process: ^7.3 || ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^13.2
- symfony/yaml: ^7.3 || ^8.0
This package is auto-updated.
Last update: 2026-08-08 21:11:47 UTC
README
This bundle gives Symfony typed services around the GDAL command-line tools:
pure argv builders, structured gdalinfo results, remote rasters over
HTTP range requests (/vsicurl/), and one supervised, shell-free execution
point with real exceptions — compiled binaries only, by design, no Python.
Enable the bundle and go.
Part of FundiStadi — open-source tooling for web, ops & data.
Why
Calling GDAL from PHP usually means hand-glued shell strings, text-scraped output, and silent breakage when the binaries move — or worse, shelling GDAL's Python scripts, whose Python↔libgdal binding pair breaks constantly across machines. This bundle handles all of it: unit-testable argv contracts, typed results, crash-isolated execution with stderr in the exception, and a locator that fails fast with an install hint — the promise is simply GDAL installed → bundle works.
Install
First the system dependency:
brew install gdal # macOS (Debian/Ubuntu: apt install gdal-bin)
Applications using Symfony Flex:
composer require fundistadi/gdal-bundle
Applications without Symfony Flex — after requiring the package, enable the bundle:
// config/bundles.php return [ // ... FundiStadi\GDALBundle\FundiStadiGDALBundle::class => ['all' => true], ];
That one line registers the binary locator (PATH discovery with actionable
errors), the supervised process runner, and the typed gdalinfo service — all
autowirable by class. Nothing else to configure.
# config/packages/fundi_stadi_gdal.yaml (optional — create it only to override) fundi_stadi_gdal: binary_dir: /opt/homebrew/bin # default: search PATH timeout: 3600 # per-process seconds
A taste
use FundiStadi\GDALBundle\Process\GdalRunner; use FundiStadi\GDALBundle\Tool\{Gdalinfo, Gdalwarp}; use FundiStadi\GDALBundle\Vsi\VsiCurl; public function __construct( private GdalRunner $gdal, private Gdalinfo $gdalinfo, ) {} // Clip a huge cloud GeoTIFF to a boundary — windowed HTTP read, no download: $this->gdal->run( Gdalwarp::create() ->cutline('boundary.geojson')->cropToCutline() ->dstNodata(255)->outputType('Byte') ->argv(VsiCurl::wrap('https://example.org/huge-raster.tif'), 'clip.tif'), ); $info = $this->gdalinfo->info('clip.tif'); $info->width; // int $info->bands[0]->noDataValue; // ?float — no text scraping
Tools: Gdalwarp (clip/reproject/convert, immutable builder), Gdalinfo (typed
inspection). Plumbing: GdalRunner (no shell, timeout, stderr-carrying
exceptions, live output streaming for progress), GdalBinaryLocator
(binary_dir or PATH; refuses *.py by design), VsiCurl (remote-raster paths).
Documentation
Read the documentation at docs/index.md — including the architecture, why Python tools are excluded, and progress streaming.
Requirements
- PHP 8.4+ · Symfony 7.3+ / 8
- GDAL compiled tools on the machine (
brew install gdal/apt install gdal-bin)
Contributing
See CONTRIBUTING.md. CI enforces the standard (php-cs-fixer, PHPStan max, PHPUnit including integration tests against real GDAL binaries) on every pull request.
Credits
License
MIT License (MIT): see the LICENSE file for more details.