This package adds to any Eloquent model the addresses: in this way will be easier to support a billing address, the shipment addresses or others.
It uses the great package matanyadaev/laravel-eloquent-spatial by Matan Yadaev.
- PHP 8.2+
- Laravel 11.x or 12.x
If you like my work, you can sponsor me.
You can install the package via composer:
composer require masterix21/laravel-addressableYou can publish and run the migrations with:
php artisan vendor:publish --provider="Masterix21\Addressable\AddressableServiceProvider" --tag="migrations"
php artisan migrateYou can publish the config file with:
php artisan vendor:publish --provider="Masterix21\Addressable\AddressableServiceProvider" --tag="config"If you're upgrading from a previous version, publish and run the meta column migration:
php artisan vendor:publish --provider="Masterix21\Addressable\AddressableServiceProvider" --tag="addressable-meta-migration"
php artisan migrateExtends an Eloquent model to supports the addresses is simple.
use Masterix21\Addressable\Models\Concerns\HasAddresses;
class User extends Model {
use HasAddresses;
}
$user->addresses(); // morphMany of `Masterix21\Addressable\Models\Address`HasAddresses is a generic trait that implements all addresses code, but if you like to handle the shipping addresses or the billing addresses there are two more specific traits.
use Masterix21\Addressable\Models\Concerns\HasBillingAddresses;
use Masterix21\Addressable\Models\Concerns\HasShippingAddresses;
class User extends Model {
use HasBillingAddresses,
HasShippingAddresses;
}
$user->billingAddress(); // Primary billing address
$user->billingAddresses(); // All billing addresses
$user->shippingAddress(); // Primary shipping address
$user->shippingAddresses(); // All shipping addressesEach trait provides convenient helper methods to create addresses:
// Generic address
$address = $user->addAddress([
'street_address1' => 'Via Roma 1',
'city' => 'Milano',
'country' => 'IT',
]);
// Billing address (is_billing is set automatically)
$address = $user->addBillingAddress([
'street_address1' => 'Via Roma 1',
'city' => 'Milano',
]);
// Shipping address (is_shipping is set automatically)
$address = $user->addShippingAddress([
'street_address1' => 'Via Roma 1',
'city' => 'Milano',
]);
// Get the primary address
$primary = $user->primaryAddress(); // ?AddressTo be sure that only one address per type will be "primary", you can use the markPrimary() method. It will mark the address as primary and will unmark the others of the same type, scoped to the same parent model.
$shippingAddress->markPrimary(); // Emits AddressPrimaryMarked and ShippingAddressPrimaryMarked
$shippingAddress->unmarkPrimary(); // Emits AddressPrimaryUnmarked and ShippingAddressPrimaryUnmarked
$billingAddress->markPrimary(); // Emits AddressPrimaryMarked and BillingAddressPrimaryMarked
$billingAddress->unmarkPrimary(); // Emits AddressPrimaryUnmarked and BillingAddressPrimaryUnmarkedThe Address model provides local scopes for fluent queries:
use Masterix21\Addressable\Models\Address;
Address::query()->primary()->get(); // All primary addresses
Address::query()->billing()->get(); // All billing addresses
Address::query()->shipping()->get(); // All shipping addresses
// Combine scopes
Address::query()->billing()->primary()->first(); // Primary billing addressYou can access the parent model from an address:
$address->addressable; // Returns the parent model (User, Company, etc.)Each address supports a meta JSON column for storing additional data without schema changes:
$user->addAddress([
'street_address1' => 'Via Roma 1',
'city' => 'Milano',
'meta' => [
'phone' => '+39 02 1234567',
'floor' => 3,
'notes' => 'Ring twice',
],
]);
$address->meta['phone']; // '+39 02 1234567'The display_address accessor formats the address as a readable string:
$address->display_address; // "Via Roma 1 - 20100 - Milano - IT"You can customize the format in config/addressable.php:
'display_format' => '{street_address1}, {street_address2}, {zip} {city}, {state}, {country}',$user->addBillingAddress([
'street_address1' => 'Via Antonio Izzi de Falenta, 7/C',
'zip' => '88100',
'city' => 'Catanzaro',
'state' => 'CZ',
'country' => 'IT',
'coordinates' => new Point(38.90852, 16.5894, config('addressable.srid')),
]);$billingAddress->coordinates = new Point(38.90852, 16.5894, config('addressable.srid'));
$billingAddress->save();// Take all addresses within 10 km
$addresses = Address::query()
->whereDistanceSphere(
column: 'coordinates',
geometryOrColumn: new Point(45.4391, 9.1906, config('addressable.srid')),
operator: '<=',
value: 10_000
)
->get();
// Take all addresses over 10 km
$addresses = Address::query()
->whereDistanceSphere(
column: 'coordinates',
geometryOrColumn: new Point(45.4391, 9.1906, config('addressable.srid')),
operator: '>=',
value: 10_000
)
->get();composer testPlease see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
If you discover any security related issues, please email l.longo@ambita.it instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.