Laravel Addressable від Luca Longo додає моделям Eloquent поліморфний зв'язок з адресами, спеціальні трейти для платіжних реквізитів та доставки, JSON-колонку для метаданих і підтримку геопросторових запитів. Усе це реалізується через одну міграцію та підключення трейта.
# Основні можливості
- Поліморфність за замовчуванням: прив’язуйте адреси до будь-якої моделі без створення додаткових таблиць зв’язків.
- Трейти для типів адрес: готові зв’язки та допоміжні методи для розділення платіжних адрес (billing) та адрес доставки (shipping).
- Керування основною адресою: методи
markPrimary()/unmarkPrimary()з автоматичною генерацією подій при зміні статусу. - Геопросторова підтримка: зберігання координат у колонці
POINTта пошук за радіусом чи відстанню (підтримує MySQL 8+, MariaDB 10.5+ та PostgreSQL з PostGIS). - JSON-колонка meta: додавання довільних даних (телефон, поверх, код домофона) без зміни структури таблиці.
- Налаштування формату: аксесор
display_address, який формує рядок адреси за шаблоном із конфігураційного файлу.
Установіть пакет та опублікуйте міграцію:
composer require masterix21/laravel-addressable
php artisan vendor:publish --provider="Masterix21\Addressable\AddressableServiceProvider" --tag="migrations"
php artisan migrate
Додайте трейт до моделі. HasAddresses забезпечує універсальний зв'язок addresses для будь-якої моделі:
use Masterix21\Addressable\Models\Concerns\HasAddresses;
class Store extends Model
{
use HasAddresses;
}
$store->addAddress([
'street_address1' => '4 Privet Drive',
'zip' => 'GU26 6HS',
'city' => 'Little Whinging',
'state' => 'Surrey',
'country' => 'GB',
]);
$store->addresses; // MorphMany моделей Address
Трейти HasBillingAddresses та HasShippingAddresses додають типізовані зв'язки для випадків, коли потрібно чітко розрізняти типи адрес:
use Masterix21\Addressable\Models\Concerns\HasBillingAddresses;
use Masterix21\Addressable\Models\Concerns\HasShippingAddresses;
class User extends Model
{
use HasBillingAddresses, HasShippingAddresses;
}
Це дає доступ до billingAddress (основна, MorphOne), billingAddresses (усі, MorphMany) та аналогічних методів для доставки. Додати адресу можна одним викликом:
$user->addBillingAddress([
'label' => 'Head Office',
'street_address1' => '221B Baker Street',
'zip' => 'NW1 6XE',
'city' => 'London',
'state' => 'England',
'country' => 'GB',
]);
JSON-колонка meta дозволяє зберігати будь-які специфічні дані без втручання в схему бази даних:
$user->addShippingAddress([
'street_address1' => '1600 Pennsylvania Ave NW',
'city' => 'Washington',
'state' => 'DC',
'country' => 'US',
'meta' => [
'phone' => '+1 202 456 1111',
'floor' => 1,
'notes' => 'Залишити на ресепшені',
],
]);
$address->meta['phone']; // '+1 202 456 1111'
Аксесор display_address форматує адресу за шаблоном із config/addressable.php. За замовчуванням він повертає рядок на кшталт "1600 Pennsylvania Ave NW - 20500 - Washington - DC - US".
// Одна адреса
echo $user->billingAddress->display_address;
// "221B Baker Street - NW1 6XE - London - England - GB"
// Усі адреси доставки
foreach ($user->shippingAddresses as $address) {
echo $address->display_address;
}
Для роботи з геоданими пакет зберігає координати як POINT (використовуючи matanyadaev/laravel-eloquent-spatial) і пропонує scope-методи для пошуку найближчих об'єктів:
use MatanYadaev\EloquentSpatial\Objects\Point;
$user->addBillingAddress([
'street_address1' => '10 Downing Street',
'city' => 'London',
'country' => 'GB',
'coordinates' => new Point(51.5034, -0.1276, config('addressable.srid')),
]);
$origin = new Point(51.5074, -0.1278, config('addressable.srid'));
// Адреси в радіусі 3 км
Address::query()->withinRadius($origin, 3_000)->get();
// 5 найближчих платіжних адрес
Address::query()->billing()->nearest($origin, 5)->get();
Методи primary(), billing() та shipping() можна вільно комбінувати. Наприклад, Address::query()->billing()->primary()->first() знайде основну платіжну адресу.
Детальніша інформація та вихідний код доступні на GitHub.