Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Addressing Laravel Package

galahad/laravel-addressing

Laravel package for managing postal addresses: bundled country, state and city data plus address models and migrations you can attach to users or orders. Seed geographic records and store structured addresses without building the schema yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install anything, check the version constraint against your app. 4.0.0 is a framework-support major — it adds Laravel 13 support and modernizes dependencies — so it is almost certainly a laravel/framework: ^13 (and likely a newer PHP floor) release. On Laravel 11 or 12, you want ^3.3, not ^4.0:

composer require glhd/laravel-addressing:^3.3   # Laravel <=12
composer require glhd/laravel-addressing:^4.0   # Laravel 13

Then the usual ten minutes. The package is small and single-purpose, so read the source before wiring it in — with zero dependents and no star history, vendor/glhd/laravel-addressing/src will tell you more than the README:

php artisan vendor:publish --provider="Glhd\Addressing\AddressingServiceProvider"
php artisan migrate

Then, in order:

  1. Diff 3.3.0 against 4.0.0 in src/. The changelog says "modernizes the dependencies a bit," which is vague enough to hide method renames or tightened signatures. Open https://github.com/glhd/laravel-addressing/compare/3.3.0...4.0.0 and scan the actual diff — that is the only reliable breaking-change list you will get from this release.
  2. Read config/addressing.php if one is published. Note the model class binding (packages like this almost always let you swap Address for your own subclass) and any country/state data source setting. This is the file you will actually edit in production.
  3. Read the migration(s). Confirm the column set (line_1, line_2, locality, administrative_area, postal_code, country_code) and, critically, the morph columns (addressable_type / addressable_id). Expect these to be unchanged in 4.0.0 — this release ships no addressing features.
  4. Find the trait. Look for something like HasAddresses in src/Concerns. That trait is the API surface you'll use 90% of the time.

Your first use case should be the simplest one that exercises the polymorphic relation:

use Glhd\Addressing\Concerns\HasAddresses;

class Customer extends Model
{
    use HasAddresses;
}

// tinker
$customer = Customer::first();
$customer->addresses()->create([
    'line_1' => '123 Main St',
    'locality' => 'Portland',
    'administrative_area' => 'OR',
    'postal_code' => '97201',
    'country_code' => 'US',
]);

$customer->addresses; // collection

If that round-trips, the package is doing its job. If the trait name or method names differ, adjust — the pattern holds regardless. Note that 4.0.0 gives you no new behavior to test against: if you are upgrading from 3.x, the only thing that can break is framework/PHP compatibility and anything the dependency modernization touched.

Implementation Patterns

Polymorphic everywhere, not belongs-to-one. The reason to reach for this package instead of five nullable columns on users is that addresses are reusable across Customer, Order, Warehouse, Vendor. Model them that way from day one. Resist the temptation to add billing_address_id foreign keys; instead expose semantic helpers on the parent model:

public function billingAddress(): ?Address
{
    return $this->addresses->firstWhere('pivot_kind', 'billing'); // or a `type` column
}

If the package ships no notion of address kind (billing vs shipping vs mailing), add a kind/label column via your own migration rather than building separate tables or separate models.

Snapshot addresses onto orders; don't reference them. This is the single most important pattern and it's independent of the package. An order must render the address as it was at checkout. Either copy the address rows into the order's own morph relation ($order->addresses()->create($customerAddress->only([...]))) or store a JSON snapshot column. If you just point the order at the same addresses row, editing a customer's address silently rewrites history.

Validate at the edge, not in the model. Put the rules in a FormRequest or a dedicated AddressData DTO:

'country_code' => ['required', 'string', 'size:2', Rule::in(array_keys($countries))],
'postal_code'  => ['required', 'string', 'max:20'],
'administrative_area' => ['nullable', 'string', 'max:64'],

Postal-code and state validation is country-specific and almost never worth hand-rolling — pair this package with a country/state data source (e.g. league/iso3166 or a states package). 4.0.0 does not refresh any country/state data, so whatever list ships is still frozen at its last content change.

Wrap writes in an application service, not controllers. Because this is an unvetted package, isolate it behind your own class so swapping implementations later is a one-file change:

class AddressBook
{
    public function saveFor(Model $owner, AddressData $data, string $kind = 'shipping'): Address
    {
        return $owner->addresses()->updateOrCreate(
            ['kind' => $kind],
            $data->toArray()
        );
    }
}

This wrapper is also your upgrade path: when 5.0.0 lands (or the package dies), the framework-version churn stops at one class.

Formatting belongs in a presenter. Addresses get rendered as multi-line blocks in emails, PDFs, and admin tables. Write one formatter — a Blade component <x-address :address="$order->shippingAddress" /> — and use it everywhere. Country-specific formatting (Japan vs US vs Germany) is a rabbit hole; start generic.

Use the package's factory in your own tests. If it ships a factory, Address::factory() keeps your test setup short. If not, write one — you'll use it constantly. On the 3.3 → 4.0 upgrade, your test suite is the thing that tells you whether the "modernized dependencies" changed behavior.

Gotchas and Tips

  • The 4.0.0 bump is compatibility, not features. No new addressing capability, no new columns, no new formatting hooks. Don't schedule an upgrade expecting to delete workarounds — plan it as a Laravel 13 migration task and nothing more.
  • Laravel 13 is brand new. The package claiming support is not the same as the ecosystem around it (factories, debugging tools, other dev dependencies) being ready. Upgrade the framework and this package together, on a branch, and run your own address tests first.
  • Pin your constraint deliberately. ^3.3 if you're staying on 11/12; ^4.0 once you move to 13. Do not use * or a bare glhd/laravel-addressing — a surprise major on a package with this release cadence is exactly the scenario pinning exists for. Commit the lockfile.
  • Publish before migrate. Running php artisan migrate before vendor:publish means you get the package's default schema and then a duplicate-table error when you publish. If you need to alter the schema, publish and edit before the first migrate, and consider --tag=migrations.
  • Morph maps. If you use Relation::enforceMorphMap(), the addressable_type column stores your alias. Changing a class name later orphans rows. Register aliases early and never rename them; if you already have data, write a one-off migration. (Relevant during a 4.0 upgrade if you also rename models.)
  • Deleting the parent. Check whether the migration uses cascadeOnDelete. If not, deleting a Customer leaves orphan addresses rows, and a later addressable_id reuse can attach a stranger's address. Add a model deleting hook or a DB constraint.
  • Indexing. The morph columns need a composite index for WHERE addressable_type = ? AND addressable_id = ?. Verify it exists; add it if the package migration omitted it. Same for postal_code and country_code if you query by region.
  • Soft-deleted addresses still appear in ->addresses unless the model uses SoftDeletes and you scope it. If the package's model doesn't, add deleted_at in your own migration plus a custom model bound via config, or hard-delete.
  • Config caching. php artisan config:cache freezes the model binding. If you swap the model via config, re-cache after deploy — and don't resolve the class name at bootstrap time in a way that breaks under cached config. Worth re-verifying after a major upgrade, since dependency modernization sometimes changes when things are resolved.
  • Country/state data goes stale. Whatever list ships is frozen at its last release, and a framework-support bump does not touch it. Treat the shipped list as a seed, not a source of truth.
  • Bus-factor risk — slightly better, not solved. A 4.0.0 with Laravel 13 support is a real signal the maintainer is still present, which is reassuring after a quiet period. It is still one maintainer with no dependents and no stars. So: (a) pin the version, (b) keep the AddressBook wrapper so removal is a day's work, (c) write your own tests around the behavior you depend on. If the address shape is genuinely simple, honestly evaluate whether 40 lines of migration plus a trait in app/Support beats a dependency here — especially since you now have to track majors just to stay on a supported framework.
  • Extension points worth checking for: a configurable model class (swap in your own with extra columns), publishable views/components for formatting, and a validation rule object. If the package offers none of these, subclassing is your escape hatch — just make sure the trait resolves the model through config() or a container binding rather than a hard-coded Address::class.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus