6.9 KiB
Core Concepts
The Three-Layer Architecture
Laravel Addresses uses three models that work together:
Address
└── AddressLink
└── AddressAssignment
Each layer has a distinct responsibility:
Layer 1: Address
The physical place. An Address is a standalone record containing street data, postal information, and optional GPS coordinates. It knows nothing about who uses it or why.
Address::create([
'street' => '350 Fifth Avenue',
'building' => 'Empire State Building',
'floor' => '32',
'room' => '3201',
'postal_code' => '10118',
'city' => 'New York',
'state' => 'NY',
'country_code' => 'US',
'latitude' => 40.748817,
'longitude' => -73.985428,
'altitude' => 443.0,
]);
All fields are nullable — an address can be as minimal as a GPS coordinate pair or as detailed as a full postal address with indoor precision.
Available fields:
| Field | Type | Description |
|---|---|---|
street |
string | Street name + house number |
street_extra |
string | c/o, suite, P.O. box |
building |
string | Building or complex name |
floor |
string | Floor/level (supports "GF", "B2", "Mezzanine") |
room |
string | Room, suite or unit identifier |
postal_code |
string | Postal / ZIP code |
city |
string | City, town, village |
state |
string | State, province, canton |
county |
string | County, district |
country_code |
string | ISO 3166-1 alpha-2 ("US", "AT", "JP") |
latitude |
float | WGS-84 decimal degrees (−90 … +90) |
longitude |
float | WGS-84 decimal degrees (−180 … +180) |
altitude |
float | Metres above mean sea level (AMSL) |
notes |
text | Free-form notes, delivery instructions |
meta |
JSON | Arbitrary extra data |
Addresses use soft deletes — calling $address->delete() sets deleted_at instead of removing the row.
Layer 2: AddressLink
The ownership pivot. An AddressLink connects an Address to an Eloquent model (User, Company, Order …) and describes the purpose of that connection.
$link = $user->addAddress([
'street' => 'Stephansplatz 1',
'city' => 'Vienna',
'country_code' => 'AT',
], AddressLinkType::Office, [
'label' => 'Main Office',
'is_primary' => true,
]);
// $link->type → AddressLinkType::Office
// $link->label → "Main Office"
// $link->address → the Address model
Key properties:
| Property | Type | Description |
|---|---|---|
type |
AddressLinkType | The purpose (Home, Office, Shipping …) |
label |
string|null | Free-text label to refine the type |
is_primary |
bool | Whether this is the primary link for its type |
active_from |
datetime|null | When the link becomes effective |
active_until |
datetime|null | When the link expires |
meta |
object|null | Arbitrary JSON data |
Important: The same address can be linked to multiple models, and each model can have multiple addresses. A user can have a Home address, an Office address, and a Billing address — each as a separate AddressLink.
Polymorphic: Uses addressable_type / addressable_id morphs, so any Eloquent model can own addresses.
Layer 3: AddressAssignment
The contextual reference. An AddressAssignment lets one model reference another model's address link without owning the address.
The problem it solves: A transport job needs a pickup and delivery address. Those addresses belong to the customer, not the job. Instead of duplicating address data, the job assigns the customer's existing address links.
// User owns the address
$link = $user->addAddress([
'street' => 'Kärntner Straße 21',
'city' => 'Vienna',
], AddressLinkType::Office);
// Job references it as "pickup"
$job->assignAddressLink($link, 'pickup');
// Later, retrieve it
$pickupAddress = $job->assignedAddressForRole('pickup');
// → Address { street: "Kärntner Straße 21", city: "Vienna" }
Key properties:
| Property | Type | Description |
|---|---|---|
address_link_id |
int | FK to the address link being referenced |
role |
string|null | Context-specific purpose ("pickup", "delivery" …) |
label |
string|null | Free-text label |
meta |
object|null | Arbitrary JSON data |
Cascade Behaviour
- Deleting an Address → all its
AddressLinkrows are cascade-deleted - Deleting an AddressLink → all its
AddressAssignmentrows are cascade-deleted - Addresses use soft deletes; links and assignments use hard deletes
Traits
The package provides two traits to add to your Eloquent models:
| Trait | Purpose | Use on |
|---|---|---|
HasAddresses |
Own and manage addresses | Models that have addresses (User, Company …) |
HasAddressAssignments |
Reference other models' addresses | Models that use addresses (Job, Order, Event …) |
A model can use both traits if it both owns and references addresses.
The AddressService
A singleton service for operations that go beyond CRUD:
// Distance between two addresses (Haversine)
address()->distanceBetween($a, $b);
// Find nearby addresses
address()->nearby($lat, $lng, $radiusKm);
// Detect duplicates
address()->findDuplicates($address);
// Format for display
address()->formatMultiline($address);
Access via the address() helper or dependency injection:
use Blax\Addresses\Services\AddressService;
public function __construct(private AddressService $addressService) {}
See the individual documentation pages for complete API references: