laravel-addresses/docs/core-concepts.md

173 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
```php
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.
```php
$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.
```php
// 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 `AddressLink` rows are cascade-deleted
- **Deleting an AddressLink** → all its `AddressAssignment` rows 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:
```php
// 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:
```php
use Blax\Addresses\Services\AddressService;
public function __construct(private AddressService $addressService) {}
```
See the individual documentation pages for complete API references:
- [HasAddresses Trait](has-addresses.md)
- [HasAddressAssignments Trait](has-address-assignments.md)
- [AddressService](address-service.md)
- [AddressLinkType Enum](address-link-types.md)
- [Customization](customization.md)