8.1 KiB
HasAddresses Trait
Add the HasAddresses trait to any Eloquent model that owns addresses.
use Blax\Addresses\Traits\HasAddresses;
class User extends Model
{
use HasAddresses;
}
class Company extends Model
{
use HasAddresses;
}
Relationships
addressLinks()
Returns all AddressLink pivot rows for this model.
$links = $user->addressLinks;
foreach ($links as $link) {
echo $link->type->label(); // "Office"
echo $link->label; // "Main Office"
echo $link->address->city; // "Vienna"
}
Return: MorphMany of AddressLink
addresses()
Returns all Address models linked to this model (many-to-many through address_links). Pivot columns are included automatically.
$addresses = $user->addresses;
foreach ($addresses as $address) {
echo $address->city;
echo $address->pivot->type; // "office"
echo $address->pivot->is_primary; // true/false
}
Return: MorphToMany of Address (with pivot: id, type, label, is_primary, active_from, active_until, meta)
Adding Addresses
addAddress(array $attributes, AddressLinkType|string|null $type = null, array $pivot = []): AddressLink
Creates a new Address record and links it to this model in one step.
use Blax\Addresses\Enums\AddressLinkType;
// Minimal
$link = $user->addAddress([
'city' => 'Vienna',
'country_code' => 'AT',
]);
// With type
$link = $user->addAddress([
'street' => '350 Fifth Avenue',
'city' => 'New York',
'postal_code' => '10118',
'country_code' => 'US',
], AddressLinkType::Office);
// With type and pivot data
$link = $user->addAddress([
'street' => 'Baker Street 221B',
'city' => 'London',
'country_code' => 'GB',
], AddressLinkType::Home, [
'label' => 'Primary Residence',
'is_primary' => true,
'meta' => ['floor' => 'ground'],
]);
Parameters:
$attributes— Address fields (street, city, latitude, etc.)$type—AddressLinkTypeenum, string value, ornull(uses config default)$pivot— Extra link data:label,is_primary,active_from,active_until,meta
Returns: The created AddressLink with the address relation loaded.
linkAddress(Address|int $address, AddressLinkType|string|null $type = null, array $pivot = []): AddressLink
Links an existing address to this model. Useful when the same address should be shared by multiple models.
use Blax\Addresses\Models\Address;
$address = Address::create([
'street' => 'Shared Office Road 1',
'city' => 'Berlin',
'country_code' => 'DE',
]);
// Link to multiple models
$user->linkAddress($address, AddressLinkType::Office);
$company->linkAddress($address, AddressLinkType::Headquarters);
// Also accepts an address ID
$user->linkAddress($address->id, AddressLinkType::Home);
Returns: The created AddressLink with the address relation loaded.
Removing Addresses
removeAddressLink(int $linkId): bool
Removes a specific address link by its pivot ID. The address record is preserved.
$link = $user->addAddress(['city' => 'Vienna'], AddressLinkType::Office);
$user->removeAddressLink($link->id); // true
detachAddress(Address|int $address): int
Removes all links between this model and a specific address.
// If the user has multiple links to the same address (e.g. Office + Billing)
$removed = $user->detachAddress($address); // 2
Returns: Number of links removed.
detachAllAddresses(): int
Removes all address links from this model.
$removed = $user->detachAllAddresses(); // 5
Returns: Number of links removed.
Note: These methods only remove the
AddressLinkpivot rows. TheAddressrecords themselves are never deleted by these operations.
Querying
addressesOfType(AddressLinkType|string $type): Collection
Get all addresses linked with a specific type.
$offices = $user->addressesOfType(AddressLinkType::Office);
$homes = $user->addressesOfType('home'); // string value also works
activeAddressLinks(): Collection
Get all address links that are currently active (respecting active_from / active_until).
$activeLinks = $user->activeAddressLinks();
foreach ($activeLinks as $link) {
echo $link->address->formatted;
}
A link is active when:
active_fromisnullOR in the past/present ANDactive_untilisnullOR in the future
primaryAddress(AddressLinkType|string|null $type = null): ?Address
Get the primary address, optionally filtered by type.
// Primary address across all types
$primary = $user->primaryAddress();
// Primary office address specifically
$primaryOffice = $user->primaryAddress(AddressLinkType::Office);
Returns: Address or null.
hasAddresses(): bool
Check whether this model has any address linked.
if ($user->hasAddresses()) {
// ...
}
hasAddressOfType(AddressLinkType|string $type): bool
Check whether this model has an address of a specific type.
if (! $user->hasAddressOfType(AddressLinkType::Billing)) {
// prompt user to add a billing address
}
Updating
setPrimaryAddressLink(int $linkId): bool
Set an address link as the primary for its type. Automatically unsets any previous primary of the same type on this model.
$officeA = $user->addAddress(['city' => 'Vienna'], AddressLinkType::Office);
$officeB = $user->addAddress(['city' => 'Berlin'], AddressLinkType::Office);
$user->setPrimaryAddressLink($officeA->id); // Vienna is primary
$user->setPrimaryAddressLink($officeB->id); // Berlin is now primary, Vienna is unset
Returns: true on success, false if the link ID was not found.
Temporal Validity
Address links support time-based activation via active_from and active_until:
$link = $user->addAddress([
'street' => 'Summer Cottage Lane 3',
'city' => 'Hallstatt',
], AddressLinkType::SecondaryResidence, [
'active_from' => '2025-06-01',
'active_until' => '2025-09-01',
]);
// Check if a specific link is active
$link->isActive(); // depends on current date
// Get only active links
$user->activeAddressLinks();
// Query scopes on AddressLink
AddressLink::active()->get();
AddressLink::expired()->get();
Working with the pivot
When accessing addresses through the addresses() relationship, all pivot columns are available:
foreach ($user->addresses as $address) {
$address->pivot->type; // "office"
$address->pivot->label; // "Main Office"
$address->pivot->is_primary; // true
$address->pivot->active_from; // "2025-01-01 00:00:00"
$address->pivot->active_until; // null
$address->pivot->meta; // "{...}"
}
Full Example
use App\Models\User;
use Blax\Addresses\Enums\AddressLinkType;
$user = User::create(['name' => 'Jane Doe', 'email' => 'jane@example.com']);
// Add a home address (primary)
$home = $user->addAddress([
'street' => 'Musterstraße 42',
'postal_code' => '1010',
'city' => 'Vienna',
'country_code' => 'AT',
'latitude' => 48.2082,
'longitude' => 16.3738,
], AddressLinkType::Home, [
'is_primary' => true,
]);
// Add an office address
$office = $user->addAddress([
'street' => 'Kärntner Straße 21',
'postal_code' => '1010',
'city' => 'Vienna',
'country_code' => 'AT',
], AddressLinkType::Office, [
'label' => 'Downtown Office',
]);
// Query
$user->hasAddresses(); // true
$user->hasAddressOfType(AddressLinkType::Shipping); // false
$user->primaryAddress(AddressLinkType::Home); // → Address { Musterstraße 42 }
$user->addressesOfType(AddressLinkType::Office); // → Collection with 1 Address
// Switch primary
$newHome = $user->addAddress(['city' => 'Graz'], AddressLinkType::Home);
$user->setPrimaryAddressLink($newHome->id);
$user->primaryAddress(AddressLinkType::Home); // → Address { city: Graz }
// Clean up
$user->removeAddressLink($office->id); // remove office link
$user->detachAllAddresses(); // remove everything