Structured addresses
A Contact is Addressable, so it holds a billing, physical or mailing address book through addresses-for-laravel. The loose value string keeps working as a fallback:
use RoundlyConsulting\Addresses\DataTransferObjects\AddressData;
use RoundlyConsulting\Addresses\Enums\AddressType;
$contact->addAddress(AddressData::make(
city: 'Bratislava', street: 'Hlavna 1', postalCode: '81101',
countryIso: 'SK', type: AddressType::Billing, isPrimary: true,
));
$contact->primaryAddress(); // the primary Address
$contact->addressesOfType(AddressType::Billing); // typed lookup
$contact->formattedAddress(); // one-line render, falls back to value- addresses(), addAddress(AddressData), primaryAddress(?AddressType), addressesOfType(AddressType), setPrimaryAddress(Address) — from the addresses package’s HasAddresses trait.
- formattedAddress() — the primary address’s one-line render, or the contact’s value when none is attached.
- AddressType cases: Default, Billing, Shipping, Home, Work, Office.
Creating contact and address together
// Build an address-type contact and its structured Address in one call:
Contacts::for($owner)
->structuredAddress([
'city' => 'Vienna', 'street' => 'Ring 3',
'postalCode' => '1010', 'countryIso' => 'AT',
'type' => AddressType::Billing,
])
->add();
// Or from the owner directly:
$owner->addStructuredAddress(AddressData::make(
city: 'Bratislava', street: 'Hlavna 1', postalCode: '81101', countryIso: 'SK',
), label: 'Main');structuredAddress() accepts an AddressData or an array (city, street, postalCode or postal_code, countryIso or country_iso, name, type, isPrimary, meta). A missing or unrecognized type is left to the host’s addresses.default_type, exactly as an address created through the addresses package. On add() the contact’s value mirrors the address’s one-line render, so existing readers keep working.
The structured address is attached as the contact’s primary Address whatever its isPrimary flag says, so primaryAddress() finds it and formattedAddress() renders it — later edits to the Address included.
Updating the address
Contacts::update() takes a structured address in ContactData::$address just as add() does: it overwrites the contact’s own Address in place, in the same transaction as the row, and the value mirrors the new render — so formattedAddress() renders the new address. A contact without one gets it attached; other addresses on the contact are left alone. A value-only update keeps the structured address and only rewords the text, so pass the address too, or edit the Address, to change what formattedAddress() renders.
A structured address is only accepted on an address contact — anything else throws InvalidContactValue. Country codes are validated by the addresses package — an unknown country throws its InvalidCountryException. Soft-deleting a contact trashes its addresses with it, restore() brings them back and forceDelete() removes them for good.
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.