The Addresses facade
The Addresses facade is the recommended entry point. Addresses::for($owner) returns the owner’s address book — works on any Eloquent model, no trait required — and the operations that need no owner scope are flat:
use RoundlyConsulting\Addresses\DataTransferObjects\AddressData;
use RoundlyConsulting\Addresses\Enums\AddressType;
use RoundlyConsulting\Addresses\Facades\Addresses;
// One owner's address book — any Eloquent model, no trait required.
$book = Addresses::for($supplier);
$book->new() // fluent PendingAddress
->type(AddressType::Work)
->in('Bratislava')->at('Somewhere 1')->postalCode('81101')->country('SK')
->save();
$book->add(AddressData::make(city: 'Košice', street: 'Main 2', postalCode: '04001', countryIso: 'SK'));
$book->all(); // Collection<Address>, oldest first
$book->primary(); // primary across all types (or null)
$book->primary(AddressType::Billing); // primary of a type
$book->ofType(AddressType::Office); // collection of a type
$book->setPrimary($address); // promote; refuses another owner's or a deleted address
$book->update($address, $data); // owner-checked full write
$book->delete($address); // owner-checked soft delete
// One address — unscoped, any owner.
Addresses::update($address, $data); // full write, dispatches AddressUpdated
Addresses::delete($address); // soft delete, dispatches AddressDeleted
Addresses::types(); // the configured type keys
Addresses::typeLabel('billing'); // 'Billing'
Addresses::countryName('sk'); // resolved name, or 'SK' without a resolverFacade methods
| Method | Returns | What it does |
|---|---|---|
Addresses::for(Model $addressable) | AddressBook | The owner’s address book — build, add, read and promote its addresses. |
Addresses::update(Address $address, AddressData $data) | Address | Full write of any address, unscoped; isPrimary: true promotes it, leaving it out demotes it. Dispatches AddressUpdated, then PrimaryAddressChanged on a promotion. |
Addresses::delete(Address $address) | void | Soft-deletes any address, unscoped; dispatches AddressDeleted. |
Addresses::types() | list<string> | The type keys configured in addresses.types — the six built-ins by default. |
Addresses::typeLabel(AddressType|string $type) | string | The type’s label: configured, translated (en and sk ship), else a headline of the key. |
Addresses::countryName(string $iso) | string | The resolved country name, or the normalised ISO code without a resolver. |
Addresses::fake() | AddressesFake | Swap in the recording fake (see Testing). |
The address book
Every read and write scoped to one owner lives on its AddressBook. $model->addressBook() on a HasAddresses model returns the same object:
| AddressBook method | Returns | What it does |
|---|---|---|
new() | PendingAddress | Start the fluent builder bound to this owner. |
add(AddressData $data) | Address | Create an address from a DTO; dispatches AddressCreated, then PrimaryAddressChanged when isPrimary promotes it. |
all() | Collection<int, Address> | Every address of the owner, oldest first. |
primary(AddressType|string|null $type = null) | ?Address | The primary address of a type (a case or a key), or the first primary of any type. |
ofType(AddressType|string $type) | Collection<int, Address> | Every address of a type (a case or a key, not checked against addresses.types), oldest first. |
update(Address $address, AddressData $data) | Address | Addresses::update() for one of this owner’s addresses; throws AddressOwnershipException when the stored row belongs to another owner or the write would move it to one — nothing is written. |
delete(Address $address) | void | Addresses::delete() for one of this owner’s addresses; same ownership check and exception. |
setPrimary(Address $address) | Address | Promote one of this owner’s addresses; throws AddressOwnershipException for another owner’s and TrashedAddressException for a soft-deleted one. |
The reads query the configured address model with whereMorphedTo('addressable', $model), so they honour a custom model and exclude soft-deleted rows.
Addresses::update() and Addresses::delete() take any address. When the caller holds an owner — a request scoped to a customer or a tenant — use the book’s update() and delete() instead: they compare the stored row’s owner by morph type and key, read under a lock, so neither a forged copy nor a row moved meanwhile gets through.
Alias
The facade is registered as the global alias Addresses by default; rename or disable it with the facade_alias config key (see Configuration). To avoid static calls altogether, inject AddressManager or run an action — see DI and actions.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.