Геопросторові дані є важливими в багатьох програмах: від картографічних сервісів до додатків для спільного використання поїздок та логістики. Здатність ефективно зберігати, запитувати та маніпулювати місцевими даними є важливим навиком для розробників, якщо ви відстежуєте флот доставочних транспортних засобів, створюєте локатор магазинів або аналізуєте географічні патерни. Завдяки геопросторовим даним ви можете співвіднести об'єкти, події та інші реальні явища з конкретною географічною областю, маркованою координатами широти та довготи.
Якщо ви створюєте додатки в цій сфері з використанням PostgreSQL, ймовірно, вам знадобиться PostGIS.
PostGIS — це розширення для реляційної бази даних PostgreSQL, яке додає підтримку зберігання, індексування та запитування геопросторових даних. PostGIS пропонує такі можливості:
Більшість хмарних провайдерів вже мають встановлений PostGIS, однак вам потрібно його активувати. Для активації PostGIS підключіться до вашої бази даних як користувач postgres
або інший суперкористувач, і виконайте:
CREATE EXTENSION postgis;
Готово! PostGIS тепер активовано.
Ви можете перевірити, яку версію ви маєте, за допомогою postgis_full_version()
.
SELECT PostGIS_Full_Version();
Якщо ви запускаєте власну систему і хочете встановити PostGIS самостійно, ось деякі базові інструкції.
Laravel за замовчуванням не підтримує багато функціоналу, необхідного для роботи з геопросторовими даними. Проте, якщо ви використовуєте PostgreSQL і маєте вже встановлений PostGIS, ви можете застосовувати методи geography
та geometry
у своїх міграціях для додавання колонок типів GEOGRAPHY
або GEOMETRY
із зазначеним просторовим типом і SRID (Ідентифікатор Просторової Системи Посилання). Наприклад:
$table->geography('coordinates', subtype: 'point', srid: 4326);
$table->geometry('positions', subtype: 'point', srid: 0);
Цей підхід може бути достатнім у певних випадках, але запити до геопросторових даних можуть бути ще простішими з пакетом Laravel-Magellan.
Laravel-Magellan спрощує роботу з PostGIS, пропонуючи інструменти, такі як парсери та генератори для GeoJSON, Well-Known Text (WKT) та Well-Known Binary (WKB). Він підтримує всі типи даних PostGIS у міграціях та надає доступ до функцій PostGIS через методи Builder, що усуває потребу в синтаксисі сирого SQL. Пакет розроблено командою Clickbar і є вдосконаленням архівного пакета mstaack/laravel-postgis
(не плутайте з іншим пакетом Laravel PostGIS, про який ми спробуємо розповісти в наступній статті).
Ви можете встановити пакет через Composer:
composer require clickbar/laravel-magellan
Потім опублікуйте та запустіть міграції:
php artisan vendor:publish --tag="magellan-migrations"
php artisan migrate
Врешті-решт, ви можете опублікувати файл конфігурації:
php artisan vendor:publish --tag="magellan-config"
Тепер замість використання стандартних типів geography
та geometry
Magellan розширює стандартний Schema Blueprint усіма функціями PostGIS, а ці методи мають префікс magellan
. Наприклад:
$table->magellanPoint('location', 4326);
$table->magellanGeometry('location', 4326);
$table->magellanGeography('location', 4326);
$table->magellanBox2D('location', 4326);
$table->magellanBox3D('location', 4326);
$table->magellanLineString('location', 4326);
і багато інших.
Magellan також надає класи геометрії для загальних геометрій, таких як Point
, LineString
, Polygon
, MultiPoint
, MultiLineString
, MultiPolygon
та GeometryCollection
.
Щоб створити об'єкт геометрії, ви можете використати метод <GeometryClass>::make
. Наприклад, щоб створити Point
, вкажіть його координати x
та y
.
$point = Point::make(26.193056, -80.161111);
Клас Point
також має фабричний метод makeGeodetic()
, який створює точку з координатами широти
, довготи
і висоти
. Проте для спрощення наші приклади використовуватимуть лише широту
та довготу
.
$point = Point::makeGeodetic(26.193056, -80.161111);
Якщо вам цікаво, геодезична точка — це конкретне місце на поверхні Землі, визначене його широтою, довготою та висотою. Геодезична лінія — це найкоротший шлях між двома точками на вигнутій поверхні Землі.
Наприклад, розглянемо сценарій зберігання стадіонів футбольних команд та їхніх розташувань.
Schema::create('stadiums', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('capacity');
$table->string('country');
$table->magellanPoint('location');
$table->timestamps();
});
Наша модель може виглядати так:
class Stadium extends Model
{
use HasFactory;
use HasPostgisColumns;
protected $guarded = [];
protected array $postgisColumns = [
'location' => [
'type' => 'geometry',
'srid' => 4326,
],
];
}
Щоб додати новий стадіон, ми можемо написати наступний код у контролері:
Stadium::create([
'name' => 'Old Trafford',
'capacity' => 74310,
'country' => 'United Kingdom',
'location' => Point::makeGeodetic(53.463493, -2.292279),
]);
Щоб отримати інформацію про розташування стадіону, використовуючи Magellan, можна написати:
$stadium = Stadium::first();
dd($stadium->location);
Результатом буде щось на кшталт:
Clickbar\Magellan\Data\Geometries\Point {#1732
#srid: 4326
#dimension: Clickbar\Magellan\Data\Geometries\Dimension {#740
+name: "DIMENSION_2D"
+value: "2D"
}
#x: -2.292279
#y: 53.463493
#z: null
#m: null
}
Якщо ми хочемо отримати значення широти, довготи та висоти, ми можемо використати методи getLatitude()
, getLongitude()
і getAltitude()
.
$stadium->location->getLatitude();
$stadium->location->getLongitude();
$stadium->location->getAltitude();
Ще однією великою перевагою використання Laravel Magellan є його розширені можливості конструктора запитів. Коли вам потрібно використовувати функцію PostGIS у конструкторі запитів, ви повинні застосувати один із методів з префіксом st
. Наприклад, stSelect
, stWhere
, stOrWhere
тощо.
Припустимо, ми перебуваємо в певному місці і хочемо дізнатися, які стадіони неподалік. Ми можемо спробувати наступне:
use Clickbar\Magellan\Data\Geometries\Point;
use Clickbar\Magellan\Database\PostgisFunctions\ST;
$myCurrentPosition = Point::makeGeodetic(53.4634962, -2.2948593);
$stadiumsNearBy = Stadium::select()
->stSelect(ST::distanceSphere($myCurrentPosition, 'location'), 'distance_to_stadium')
->stWhere(ST::distanceSphere($myCurrentPosition, 'location'), '<=', 20000)
->get();
Примітка: Відстані, які повертає ST::distanceSphere()
, вимірюються в метрах.
Laravel Magellan також забезпечує просту валідацію геометрії у форматі GeoJSON. Наприклад:
class StoreStadiumRequest extends FormRequest
{
use TransformsGeojsonGeometry;
public function rules(): array
{
return [
'name' => ['required', 'string'],
'capacity' => ['required', 'integer'],
'country' => ['required', 'string'],
'location' => ['required', new GeometryGeojsonRule([Point::class])],
];
}
public function geometries(): array
{
return ['location'];
}
}
Використовуючи PostgreSQL та розширення PostGIS, розробники можуть ефективно зберігати, запитувати та маніпулювати даними про місцезнаходження. Laravel-Magellan ще більше спрощує цей процес, пропонуючи зручний інтерфейс для функцій PostGIS.
Дізнайтеся більше про Laravel Magellan та перегляньте вихідний код на Github