4.6 KiB
Customization
Custom Model Classes
You can extend any of the three package models with your own. This is useful for adding custom methods, relationships, accessors or validation logic.
1. Create your custom model
// app/Models/CustomAddress.php
namespace App\Models;
use Blax\Addresses\Models\Address as BaseAddress;
class CustomAddress extends BaseAddress
{
public function getFullAddressAttribute(): string
{
return "{$this->street}, {$this->postal_code} {$this->city}, {$this->country_code}";
}
public function geocode(): self
{
// your geocoding logic
return $this;
}
}
2. Update the config
// config/addresses.php
'models' => [
'address' => \App\Models\CustomAddress::class,
'address_link' => \Blax\Addresses\Models\AddressLink::class,
'address_assignment' => \Blax\Addresses\Models\AddressAssignment::class,
],
The package resolves all model classes through config('addresses.models.…'), so your custom class will be used everywhere — in relationships, service methods, and traits.
Example: Custom AddressLink
namespace App\Models;
use Blax\Addresses\Models\AddressLink as BaseAddressLink;
class CustomAddressLink extends BaseAddressLink
{
protected static function booted()
{
static::creating(function (self $link) {
// Auto-set label from type if not provided
if (! $link->label) {
$link->label = $link->type->label();
}
});
}
}
'models' => [
'address_link' => \App\Models\CustomAddressLink::class,
],
Custom Table Names
Change the table names if they collide with existing tables in your application:
// config/addresses.php
'table_names' => [
'addresses' => 'company_addresses',
'address_links' => 'company_address_links',
'address_assignments' => 'company_address_assignments',
],
Important: Update the published migration to match these names before running php artisan migrate. The migration stub reads from the config, so if you publish the config first and then the migration, the table names will be picked up automatically.
Custom Default Link Type
Change the default AddressLinkType applied when adding an address without specifying a type:
// config/addresses.php
'default_link_type' => \Blax\Addresses\Enums\AddressLinkType::Home,
Now $user->addAddress(['city' => 'Vienna']) will use Home instead of Other.
Using the Meta Column
All three models (Address, AddressLink, AddressAssignment) include a meta JSON column for storing arbitrary data. The column is cast to object.
// On addresses — store extra data
$link = $user->addAddress([
'street' => 'Main Street 1',
'city' => 'Vienna',
'meta' => [
'plus_code' => '8FWR4HCJ+XX',
'what3words' => 'index.home.raft',
'timezone' => 'Europe/Vienna',
],
]);
// On address links — store context about the relationship
$link = $user->addAddress(['city' => 'Vienna'], AddressLinkType::Office, [
'meta' => [
'department' => 'Engineering',
'access_code' => '4521',
],
]);
// On address assignments — store context about the assignment
$job->assignAddressLink($link, 'delivery', [
'meta' => [
'time_window' => '09:00-12:00',
'priority' => 'express',
],
]);
// Reading meta
$address->meta->plus_code; // "8FWR4HCJ+XX"
$link->meta->department; // "Engineering"
$assignment->meta->time_window; // "09:00-12:00"
Model Bindings
The service provider registers model bindings so that resolving a package model through the container returns the configured (possibly customised) class:
// Always resolves to your custom class if configured
$address = app(\Blax\Addresses\Models\Address::class);
This means type-hinting the base class in dependency injection will automatically resolve to your custom model.
Extending the AddressService
The AddressService is registered as a singleton. To add custom methods, extend it and rebind:
namespace App\Services;
use Blax\Addresses\Services\AddressService;
use Blax\Addresses\Models\Address;
class CustomAddressService extends AddressService
{
public function geocode(Address $address): Address
{
// your geocoding implementation
return $address;
}
}
In a service provider:
$this->app->singleton(
\Blax\Addresses\Services\AddressService::class,
\App\Services\CustomAddressService::class
);
The address() helper and all DI injection will now resolve your custom service.