markup/addressing
Address management for Laravel: store, format, and validate postal addresses with country and subdivision data, polymorphic address models, and helpers for clean, consistent address handling across your application.
Architecture fit. markup/addressing is a plain PHP domain library — no Laravel service provider, facade, config, migration, or Blade directives are advertised. That makes it architecturally safe (no framework coupling, no global state) but ergonomically a poor fit for a Laravel codebase out of the box: you own the wiring. Expect to add a singleton binding, a config/addressing.php, and a thin facade yourself. The library's job — rendering a postal address in country-specific formats — is a pure function over a value object, so it slots in cleanly as a presentation-layer utility used by Blade views, API resources, PDF/invoice generators, and mail-merge jobs.
Integration feasibility. Mechanically trivial: composer require markup/addressing, then wrap. The real question is whether the dependency graph resolves on a modern stack. With a last release of 2019-04-15, the package predates PHP 7.4 typed properties, PHP 8 union types, and Laravel 8–11. It is almost certainly a thin wrapper around commerceguys/addressing (the de-facto PHP implementation of CLDR/UPU address formats), which has moved on across major versions. Feasibility therefore hinges on a transitive-dependency resolution check, not on the package's own code.
Technical risk. High, and concentrated almost entirely in supply chain rather than code quality. Concretely:
commerceguys/addressing will likely conflict with current releases, or silently pin you to an old major that lacks PHP 8.1+ compatibility. This is the most probable outright blocker.Key questions to answer before committing engineering time:
commerceguys/addressing directly? If the delta is a handful of formatting helpers, the wrapper is not worth the dependency.composer.json constraints, and does composer why-not resolve cleanly against our target PHP/Laravel matrix?Stack fit. Treat this as a utility adapter, not a platform component. It belongs behind a first-party interface — App\Contracts\AddressFormatter with methods like format(Address $address, string $locale, string $script): string — so that the concrete implementation is an implementation detail the rest of the codebase never names. This single decision converts an abandoned-package risk into a one-file swap.
Migration path. Do not integrate the package directly at call sites. Sequence it as:
composer require. Run the package's own tests if present. Resolve or document conflicts. If resolution fails, stop — go to commerceguys/addressing directly and write ~150 lines of formatting code yourself.AddressFormatter with a MarkupAddressingFormatter class. No other class in the app imports the vendor namespace.commerceguys/addressing (actively maintained, CLDR-backed), symfony/intl, or a vendor API (Lob, SmartyStreets, Google libaddressinput) are the drop-ins behind the same interface.Compatibility. Pin loosely in our app (^x.y) but commit composer.lock. Add the package's major version to our dependency-review checklist. Run CI against our full PHP/Laravel matrix. Watch for E_DEPRECATED noise on PHP 8.2+ — a 2019 library is a strong candidate for implicit-nullable and dynamic-property warnings that will flood logs.
Sequencing. Adapter and fixtures before package choice; package choice before integration; read path before write path; one release cycle of observation before expanding blast radius. Total elapsed effort for a competent Laravel developer: 3–5 days, of which maybe half a day touches the vendor package.
Maintenance. Assume we are the maintainer. Budget: ~2–4 hours per quarter for dependency bumps and data refresh, plus unbounded time if a transitive CVE lands. Plan to fork into our VCS namespace (ourorg/addressing) on day one — MIT permits it, and it removes the "upstream might vanish" tail risk and lets us apply PHP 8 patches locally without waiting on a maintainer who is not coming. This is the single highest-leverage operational decision here.
Support. No vendor. No SLA. GitHub Issues against a repo with one star is functionally a void. Internal support means: whoever writes the adapter owns the formatter, and the fixture table is the documentation. Ensure at least two engineers can read that table.
Scaling. Negligible runtime concern. Formatting is a pure CPU transform over a small in-memory data set; the dominant cost is a one-time country-data load per process (a few hundred KB), which OPcache amortizes. For batch workloads — nightly invoice generation, bulk shipping-label runs — cache rendered strings keyed by (address hash, locale) rather than re-formatting. The scaling risk is not compute; it is data staleness at scale: one wrong format template applied to 50,000 labels is a recall, not a bug ticket.
Failure modes, ranked by impact:
| Failure | Likelihood | Impact | Detection |
|---|---|---|---|
Transitive dependency conflict blocks composer update |
High | Medium — freezes upgrades for the whole app | CI, day one |
| Silent misformatting for an edge-case country | Medium | High — printed labels, returned shipments, compliance issues | Fixture table, spot audits |
| Stale reference data after a postal reform | Medium (cumulative) | Medium–High | Annual data review |
| Inherited CVE, no upstream fix | Low–Medium | High | composer audit / Dependabot |
| PHP 8.x deprecation spam degrades logs | High | Low | CI |
| Upstream repo deletion | Low | Low — mitigated by fork | — |
The distinguishing characteristic of this package's failure profile is that it fails silently and confidently. There is no exception for "I don't know this country's format" in most implementations of this pattern — there is a plausible-looking wrong string. Design accordingly: log a warning when the formatter is asked for a country/script combination not covered by the fixture table, and route those to a human.
Ramp-up. Low. The API surface is a value object plus a formatter; a mid-level Laravel developer is productive in half a day, and the adapter boundary means they never need to learn the vendor internals. The non-obvious learning is domain knowledge, not code: CLDR address-format metadata, UPU conventions, script/locale handling (a Japanese address rendered in Latin transliteration follows different ordering rules than one rendered in Kanji), and the difference between formatting and validation. Budget a short internal write-up on those; it will outlive the package.
Recommendation. Do not adopt as a direct dependency. Adopt the problem, solve it behind an AddressFormatter interface with a fixture-driven contract test suite, and evaluate commerceguys/addressing directly first. Reach for markup/addressing only if it demonstrably saves meaningful work over that baseline — and if you do, fork it immediately. The package is a 2019 artifact with no users and no maintainer; the only defensible posture is to treat it as vendored source code you are choosing to own, not as a dependency you are consuming.
How can I help you explore Laravel packages today?