Обробка геопросторових даних за допомогою Laravel Magellan

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 04 грудня, 2024
Ви готові відкрити нові горизонти у роботі з геопросторовими даними в Laravel? Дізнайтеся, як за допомогою PostGIS та пакету Laravel-Magellan можна легко зберігати, запитувати та маніпулювати інформацією про розташування, перетворюючи ваші проекти на вражаючі рішення у сфері картографії та геолокації!

Геопросторові дані є важливими в багатьох програмах: від картографічних сервісів до додатків для спільного використання поїздок та логістики. Здатність ефективно зберігати, запитувати та маніпулювати місцевими даними є важливим навиком для розробників, якщо ви відстежуєте флот доставочних транспортних засобів, створюєте локатор магазинів або аналізуєте географічні патерни. Завдяки геопросторовим даним ви можете співвіднести об'єкти, події та інші реальні явища з конкретною географічною областю, маркованою координатами широти та довготи.

Якщо ви створюєте додатки в цій сфері з використанням PostgreSQL, ймовірно, вам знадобиться PostGIS.

# PostGIS

PostGIS — це розширення для реляційної бази даних PostgreSQL, яке додає підтримку зберігання, індексування та запитування геопросторових даних. PostGIS пропонує такі можливості:

Більшість хмарних провайдерів вже мають встановлений PostGIS, однак вам потрібно його активувати. Для активації PostGIS підключіться до вашої бази даних як користувач postgres або інший суперкористувач, і виконайте:

CREATE EXTENSION postgis;

Готово! PostGIS тепер активовано.

Ви можете перевірити, яку версію ви маєте, за допомогою postgis_full_version().

SELECT PostGIS_Full_Version();

Якщо ви запускаєте власну систему і хочете встановити PostGIS самостійно, ось деякі базові інструкції.

# Laravel та Геопросторові Дані

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

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