{"id":13784420,"url":"https://github.com/heymoon-cc/php-vector-tile-data-provider","last_synced_at":"2026-01-11T10:49:32.772Z","repository":{"id":61920102,"uuid":"556105367","full_name":"heymoon-cc/php-vector-tile-data-provider","owner":"heymoon-cc","description":"Serve or write Mapbox Vector Tile 2.1 using PHP 8.1","archived":false,"fork":false,"pushed_at":"2025-01-10T18:09:40.000Z","size":1178,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T03:03:37.901Z","etag":null,"topics":["mapbox-vector-tile","tileserver-gl","vt-pbf"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/heymoon/vector-tile-data-provider","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/heymoon-cc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-23T04:04:57.000Z","updated_at":"2025-01-10T18:09:44.000Z","dependencies_parsed_at":"2024-08-03T19:13:13.329Z","dependency_job_id":null,"html_url":"https://github.com/heymoon-cc/php-vector-tile-data-provider","commit_stats":{"total_commits":17,"total_committers":1,"mean_commits":17.0,"dds":0.0,"last_synced_commit":"d0a82d62ebdd15bad9c8a9797bc15f94c464cb67"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heymoon-cc%2Fphp-vector-tile-data-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heymoon-cc%2Fphp-vector-tile-data-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heymoon-cc%2Fphp-vector-tile-data-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heymoon-cc%2Fphp-vector-tile-data-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heymoon-cc","download_url":"https://codeload.github.com/heymoon-cc/php-vector-tile-data-provider/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253621336,"owners_count":21937508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mapbox-vector-tile","tileserver-gl","vt-pbf"],"created_at":"2024-08-03T19:00:42.850Z","updated_at":"2026-01-11T10:49:32.766Z","avatar_url":"https://github.com/heymoon-cc.png","language":"PHP","funding_links":[],"categories":["Parsers \u0026 Generators"],"sub_categories":[],"readme":"# Mapbox vector tiles library for PHP\n[![Version](https://poser.pugx.org/heymoon/vector-tile-data-provider/v)](https://packagist.org/packages/heymoon/vector-tile-data-provider)\n[![PHP Version Require](https://poser.pugx.org/heymoon/vector-tile-data-provider/require/php)](https://packagist.org/packages/heymoon/vector-tile-data-provider)\n[![Test](https://github.com/heymoon-cc/php-vector-tile-data-provider/actions/workflows/test.yaml/badge.svg)](https://github.com/heymoon-cc/php-vector-tile-data-provider/actions/workflows/test.yaml)\n[![Maintainability](https://qlty.sh/badges/810dfe02-6be3-4375-8d4a-db19daa43fb7/maintainability.svg)](https://qlty.sh/gh/heymoon-cc/projects/php-vector-tile-data-provider)\n[![Code Coverage](https://qlty.sh/badges/810dfe02-6be3-4375-8d4a-db19daa43fb7/test_coverage.svg)](https://qlty.sh/gh/heymoon-cc/projects/php-vector-tile-data-provider)\n[![Matrix](https://img.shields.io/matrix/php-vector-tile-data-provider%3Aheymoon.cc?fetchMode=guest)](https://matrix.to/#/#php-vector-tile-data-provider:heymoon.cc)\n\nSymfony + Redis demo: **\u003chttps://map.heymoon.cc\u003e**\n---\n![Screenshot](https://repository-images.githubusercontent.com/556105367/1ae4eed2-6718-45ea-909e-16aad3ef7dc9)\n\nBasic [Leaflet](https://leafletjs.com/)-based map example with realtime Symfony backend performance preview.\nWhen \"Use cache\" checkbox is not active, `getTileMVT` function is called on each request without any additional static\ncaching strategy. With \"Use cache\" option, backend renders each tile only once and stores results in Redis.\nTwo layers are requested separately for benchmarking:\n* Polygons based off 976K GeoJSON with 7 string properties.\n* Lines based off 2.8M GeoJSON with 139 optional properties.\n\nIt only has 1 CPU and low RAM at its disposal so please be gentle.\n## Summary\n\nConvert [OpenGIS](https://www.ogc.org/standards/sfa) data loaded by [brick/geo](https://github.com/brick/geo) directly\nto [Mapbox Vector Tile 2.1](https://github.com/mapbox/vector-tile-spec/tree/master/2.1) format. Focused on\nfrequent source data changes delivery with the lowest latency possible. Process data fast with [GEOS](https://libgeos.org) C/C++ library via\n[PHP integration](https://git.osgeo.org/gitea/geos/php-geos.git) with custom update trigger to fit your needs.\nPerform SRID transformation and Douglas-Peucker simplification faster than ever.\n___\nAdditional: convert MVT tiles to SVG (debug purposes only, not designed for production).\nInstall [meyfa/php-svg](https://github.com/meyfa/php-svg) to use this feature.\n\n## Motivation\nIf you want to display current weather conditions or some moving objects on your map, it's good to be able to generate\nyour tileset directly on receiving updates from data provider, for example when reading GeoJSON from HTTP API response.\nThe bottleneck is usually encountered with the following:\n* Necessity to use intermediate storage compatible with some 3rd-party utility\nfor preparing MVT\n* Generating tiles for large zoom levels\n* Sharing update between server nodes, especially if it's stored in single\n[MBTiles](https://github.com/mapbox/mbtiles-spec) file.\nOf course, you can [generate tiles from your PostGIS database](https://github.com/mapbox/postgis-vt-util) which will allow\nfor frequent source data update, but you'll probably have a hard time battling performance drops after each index update.\nSo, with standard toolset you'll be forced to choose between low update latency and low response time.\nBut it shouldn't be that way. This is where this library could help.\n\n## How is it faster\nMost likely your data doesn't always change in every tile. And even if it does, if you'll look into request distribution\nby zoom, you'll probably notice that most of generated tiles smaller than, for example, zoom 18, are rarely requested\nbetween data changes but take the most of update's time, so you may want to prioritize some tiles more than others.\nWith enough flexibility it is possible to invalidate parts of previous result and process in advance only frequently \nrequested scales, leaving the rest to on-demand processing and updating MVT cache only on HTTP-request.\nWith this library you'll be able to implement tight integration with the specific update scenario\nand minimize redundant calculations with custom update pipeline. Also, since [GEOS](https://libgeos.org)\nfunctions can be called directly, it's much easier to scale.\n\n## Installation\n`composer require heymoon/vector-tile-data-provider`\n\nYou must explicitly generate protobuf classes from your project root:\n\n`protoc --proto_path=./vendor/heymoon/vector-tile-data-provider/proto --php_out=./vendor/heymoon/vector-tile-data-provider/proto/gen ./vendor/heymoon/vector-tile-data-provider/proto/vector_tile.proto`\n\nInstall `php-geos` and `php-protobuf` extensions for best performance. Example Dockerfile for\n[Alpine 3.16 with PHP 8.1](https://hub.docker.com/layers/library/php/8.1-alpine3.16/images/sha256-298daac152760e2510ff283b0785c8feef72a2b134b27af918a80e40f26c1bb8):\n```Dockerfile\nFROM php:8.1-alpine3.16\nRUN apk add --no-cache --virtual .build-deps \\\n    $PHPIZE_DEPS \\\n    geos-dev \\\n    git\nRUN apk add --no-cache protoc geos\nRUN pecl install protobuf \\\n    \u0026\u0026 docker-php-ext-enable protobuf \\\n\t\u0026\u0026 git clone https://git.osgeo.org/gitea/geos/php-geos.git /usr/src/php/ext/geos \u0026\u0026 cd /usr/src/php/ext/geos \u0026\u0026 \\\n\t./autogen.sh \u0026\u0026 ./configure \u0026\u0026 make \u0026\u0026 \\\n\techo \"extension=/usr/src/php/ext/geos/modules/geos.so\" \u003e /usr/local/etc/php/conf.d/docker-php-ext-geos.ini\nRUN apk del -f .build-deps \u0026\u0026 rm -rf /tmp/* /var/cache/apk/*\n# run \"composer install\" and then...\nRUN protoc --proto_path=./vendor/heymoon/vector-tile-data-provider/proto --php_out=./vendor/heymoon/vector-tile-data-provider/proto/gen ./vendor/heymoon/vector-tile-data-provider/proto/vector_tile.proto\n```\n\n## Provides\n* `HeyMoon\\VectorTileDataProvider\\Entity\\Source` and `Entity\\SourceProxy` (storing geometries as WKB until evaluated) instances initialized by `HeyMoon\\VectorTileDataProvider\\Factory\\SourceFactory` for easy data load\nfrom `Brick\\Geo\\IO\\GeoJSON\\FeatureCollection` or manually populated `Brick\\Geo\\Geometry` objects.\n* `HeyMoon\\VectorTileDataProvider\\Service\\SpatialService` for cheap spatial system transformation.\n* `HeyMoon\\VectorTileDataProvider\\Service\\GridService` and resulting `HeyMoon\\VectorTileDataProvider\\Entity\\Grid` instance for filtering geometries\nvisible only in particular tile and assigned to particular thread (threading can be achieved through providing filter\ncallback function in `GridService::getGrid` to skip tiles based on position). This operation is the most demanding of\nRAM, but could be completed much faster than full result generation.\n* `HeyMoon\\VectorTileDataProvider\\Service\\TileService` for\n[Mapbox Vector Tile 2.1](https://github.com/mapbox/vector-tile-spec/tree/master/2.1) generation, presumably in\n`Grid::iterate` callback or HTTP request, reading required geometries from pre-saved `GridService` groups.\nGeometry simplification is performed only on `TileService::getTileMVT`.\n* `HeyMoon\\VectorTileDataProvider\\Service\\ExportService` for basic export to `.mvt`, to serve tileset as static files via NGINX,\nor `.svg` for result preview.\n* `HeyMoon\\VectorTileDataProvider\\Factory\\TileFactory` for parsing and merging ready vector tiles.\n\n## Spatial systems\nBy default, grid is expected to be aligned with the\n[Web Mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection), which is most likely different from\nyour original data source spatial reference system. In order to process inputs with arbitrary SRID, library includes\ncustom implementation of spatial transformation engine in `HeyMoon\\VectorTileDataProvider\\Service\\SpatialService` (since SRID\ntransformation is unsupported by php-geos and has performance issues in PostGIS). Following geometries are currently\nsupported out-of-the-box:\n* SRID 3857 (aka [Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator_projection)\nmentioned earlier).\n* SRID 4326 (aka [WGS 84](https://en.wikipedia.org/wiki/World_Geodetic_System#1984_version), most\ncommonly used, default for GeoJSON [according to RFC 7946](https://www.rfc-editor.org/rfc/rfc7946.html)).\n\nAdditional projections can be described as\nsubclass of `SpatialProjectionInterface` and passed in `supports` function of a new class extended\nfrom `AbstractProjectionRegistry`. Projection class should implement conversion of point coordinates on 2D\nsurface from WGS 84 to the required spatial system and the reverse transformation function.\n## Example usage in Symfony:\n### DI configuration:\n```yaml\nservices:\n  Brick\\Geo\\IO\\GeoJSONReader: ~\n  Brick\\Geo\\Engine\\GeometryEngine:\n    class: 'Brick\\Geo\\Engine\\GEOSEngine'\n  HeyMoon\\VectorTileDataProvider\\Contract\\GeometryCollectionFactoryInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Factory\\GeometryCollectionFactory'\n  HeyMoon\\VectorTileDataProvider\\Contract\\SourceFactoryInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Factory\\SourceFactory'\n  HeyMoon\\VectorTileDataProvider\\Contract\\ProjectionRegistryInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Registry\\BasicProjectionRegistry'\n  HeyMoon\\VectorTileDataProvider\\Contract\\ExportFormatInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Registry\\ExportFormatRegistry'\n  HeyMoon\\VectorTileDataProvider\\Contract\\SpatialServiceInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Service\\SpatialService'\n  HeyMoon\\VectorTileDataProvider\\Contract\\GridServiceInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Service\\GridService'\n  HeyMoon\\VectorTileDataProvider\\Contract\\TileServiceInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Service\\TileService'\n  HeyMoon\\VectorTileDataProvider\\Contract\\ExportServiceInterface:\n    class: 'HeyMoon\\VectorTileDataProvider\\Service\\ExportService'\n```\n### Action:\n```php\nuse Brick\\Geo\\IO\\GeoJSONReader;\nuse Brick\\Geo\\Exception\\GeometryException;\nuse HeyMoon\\VectorTileDataProvider\\Entity\\TilePosition;\nuse HeyMoon\\VectorTileDataProvider\\Contract\\SourceFactoryInterface;\nuse HeyMoon\\VectorTileDataProvider\\Contract\\GridServiceInterface;\nuse HeyMoon\\VectorTileDataProvider\\Contract\\TileServiceInterface;\nuse HeyMoon\\VectorTileDataProvider\\Contract\\ExportServiceInterface;\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputArgument;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n#[AsCommand(name: 'app:export')]\nclass ExportCommand extends Command\n{\n    public function __construct(\n        private readonly GeoJSONReader $geoJSONReader,\n        private readonly SourceFactoryInterface $sourceFactory,\n        private readonly GridServiceInterface $gridService,\n        private readonly TileServiceInterface $tileService,\n        private readonly ExportServiceInterface $exportService\n    )\n    {\n        parent::__construct();\n    }\n\n    public function configure()\n    {\n        $this-\u003eaddArgument('in', InputArgument::REQUIRED);\n        $this-\u003eaddArgument('out', InputArgument::REQUIRED);\n        $this-\u003eaddOption('zoom', 'z', InputOption::VALUE_OPTIONAL);\n        $this-\u003eaddOption('type', 't', InputOption::VALUE_OPTIONAL,\n            'mvt for .mvt or svg for .svg');\n    }\n\n    public function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $source = $this-\u003esourceFactory-\u003ecreate();\n        try {\n            $source-\u003eaddCollection('export', $this-\u003egeoJSONReader-\u003eread(file_get_contents($input-\u003egetArgument('in'))));\n            $grid = $this-\u003egridService-\u003egetGrid($source, $input-\u003egetOption('zoom') ?? 0);\n            $path = $input-\u003egetArgument('out');\n            $type = $input-\u003egetOption('type') ?? 'mvt';\n            $grid-\u003eiterate(fn (TilePosition $position, array $data) =\u003e\n                $this-\u003eexportService-\u003edump(\n                    $this-\u003etileService-\u003egetTileMVT($data, $position), \"$path/$position.$type\")\n            );\n        } catch (GeometryException $e) {\n            $output-\u003ewriteln(\"Data error: {$e-\u003egetMessage()}\");\n            return 1;\n        }\n        return 0;\n    }\n}\n```\nTested with [Symfony 6.1](https://symfony.com/releases/6.1).\n## Export result\nIn real life scenario instead of dumping SVG files you would write data in your database of choice. For example, you\ncould create [MBTiles](https://github.com/mapbox/mbtiles-spec) file readable by\n[tileserver-gl](https://github.com/maptiler/tileserver-gl). This is achievable\nwith the SQLite database containing schema from\n[the latest specification description](https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md).\nAlternatively you could store only the grid partitioning result for on-demand generation in your own vector data source\ncontroller on PHP later (useful if faster data update is needed).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheymoon-cc%2Fphp-vector-tile-data-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheymoon-cc%2Fphp-vector-tile-data-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheymoon-cc%2Fphp-vector-tile-data-provider/lists"}