Skip to content

Addresses

Addresses attach to users, companies, or customers the same way contacts do — a polymorphic relation with automatic primary-address management, plus a proper Country relation rather than a free-text country field.

Managing a model's addresses

Attaching to any model

php
// The owning model, and a real, queryable country record (app/Concerns/IsAddress.php)...
$address->addressable() : Illuminate\Database\Eloquent\Relations\MorphTo
$address->country() : Illuminate\Database\Eloquent\Relations\BelongsTo

Trait Methods (HasAddresses)

php
// Every address belonging to this model, and just the primary one...
$model->addresses() : Illuminate\Database\Eloquent\Relations\MorphMany
$model->primaryAddress() : Illuminate\Database\Eloquent\Relations\MorphOne

// Determine whether this model has any addresses...
$model->hasAddresses() : bool

User, Company, and Customer gain these through App\Concerns\HasAddresses. Countries are reference data seeded by CountryPreparer (see Installation) — the country_id foreign key means you get a real, queryable country record rather than a string to parse.

Status

AddressStatus is Active, Inactive, Pending, ManuallyFlagged, or AutoFlagged. The two "flagged" statuses exist for verification workflows — for example, marking an address that failed a validation check (AutoFlagged) versus one an admin manually queued for review (ManuallyFlagged), separately from a simple active/inactive toggle.

Automatic primary management

Identical mechanism to Contacts — the first address for a given owner becomes primary automatically, and saving a new primary demotes the rest.

php
// The current primary address for a given owner...
Address::getPrimaryFor(Model $addressable) : App\Models\Address|null

Actions (app/Actions/Addresses/)

php
// Create an address...
CreateAddress::create(array $input) : App\Models\Address

// Update an address...
UpdateAddress::update(Address $address, array $input) : void

// Delete an address (refuses to delete the primary one)...
DeleteAddress::delete(Address $address) : void

Listing and filtering go through App\Query\AddressesQuery — the same spatie/laravel-query-builder pattern used across every resource in Reshape.