Updating & deleting
Updating
Addresses::update() writes an AddressData onto an existing address in one transaction, promotes it when isPrimary is true, dispatches AddressUpdated (then PrimaryAddressChanged for a promotion) and returns the refreshed model. It runs UpdateAddressAction, which you can also call directly:
use RoundlyConsulting\Addresses\DataTransferObjects\AddressData;
use RoundlyConsulting\Addresses\Facades\Addresses;
$address = Addresses::update($address, AddressData::make(
city: 'Bratislava',
street: 'Somewhere 5',
postalCode: '81102',
countryIso: 'SK',
// AddressData is a full write — carry over what should not change
name: $address->name,
type: $address->type,
isPrimary: $address->is_primary,
meta: $address->meta,
));The update is a full write: every DTO field replaces the stored value. Leaving out name, type, isPrimary or meta resets them — name and meta to null, type to the configured default_type, and isPrimary to false, which demotes the address — so carry over whatever should not change, as above. Asking a soft-deleted address to become primary throws TrashedAddressException.
A plain $address->update([...]) still works, but it skips country normalisation, the primary invariant and the AddressUpdated event.
Deleting
Addresses::delete() soft-deletes an address, so an accidental removal can be undone. AddressDeleted is dispatched from the model’s deleted hook, which runs for delete() and forceDelete() alike:
use RoundlyConsulting\Addresses\Address;
use RoundlyConsulting\Addresses\Facades\Addresses;
Addresses::delete($address); // soft delete; dispatches AddressDeleted
$address->restore(); // bring it back (as primary only if the slot is free)
$address->forceDelete(); // permanent removal (dispatches AddressDeleted too)
Address::onlyTrashed()->get(); // what was removed
$customer->addresses()->withTrashed()->get(); // including removed onesDeleting the primary leaves its type without one until you promote another. The deleted address keeps its flag, so restore() brings it back as the primary — but only while no other live primary holds the owner + type slot; otherwise it returns as a plain address (see Primary addresses).
When the owner is deleted
The morph column has no foreign key, so deleting an owner leaves its addresses behind. Delete them per model so AddressDeleted fires for each — a bulk $customer->addresses()->delete() also soft-deletes, but fires no model events:
// addresses are not removed with their owner — there is no foreign key or cascade.
// delete them per model so AddressDeleted fires for each:
$customer->addresses->each->delete();
$customer->delete();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.