Skip to content

Instantly share code, notes, and snippets.

@boris-glumpler
Last active December 20, 2024 05:41
Show Gist options
  • Save boris-glumpler/428c2a6823306133256fdd6cb68c9a77 to your computer and use it in GitHub Desktop.
Save boris-glumpler/428c2a6823306133256fdd6cb68c9a77 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Services;
use App\Models\Country;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use ShabuShabu\PostGIS\Expressions\As;
use Tpetry\QueryExpressions\Language\Alias;
use ShabuShabu\PostGIS\Expressions\Simplify;
use ShabuShabu\PostGIS\Expressions\Transform;
use ShabuShabu\PostGIS\Expressions\TileEnvelope;
use Symfony\Component\HttpFoundation\StreamedResponse;
class CountryTiles extends Controller
{
public function __invoke(int $z, int $x, int $y): StreamedResponse
{
$stream = DB::query()
->withExpression(
'mvtgeom',
DB::query()
->select([
new Alias(
new As\MvtGeom(
new Transform('t.geom', 3857),
new TileEnvelope($z, $x, $y),
),
'geom',
),
't.id',
't.name',
])
->from(
Country::query()->select([
new Alias(new Simplify('geom', 0.1), 'geom'),
'id',
'name',
]),
't'
)
)
->select(new Alias(new As\MVT('mvtgeom.*', 'countries'), 'pbf'))
->from('mvtgeom')
->value('pbf');
abort_unless(is_resource($stream), Response::HTTP_NO_CONTENT);
defer(static fn () => fclose($stream));
return response()->stream(function () use ($stream) {
while (! feof($stream) && connection_status() === 0) {
echo fread($stream, 8192);
ob_flush();
flush();
}
}, Response::HTTP_OK, [
'Content-Type' => 'application/vnd.mapbox-vector-tile',
]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment