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

Postal Code Laravel Package

rmsramos/postal-code

rmsramos/postal-code is a Laravel package for working with postal codes: validate, format, and look up address data through a clean, configurable API. Lightweight and easy to drop into forms, checkout, or shipping flows.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require rmsramos/postal-code. Use ^0.1.1 or later if you're on Laravel 11 — v0.1.1 is the first release that declares Laravel 11 support, so earlier constraints can fail dependency resolution or silently pull an incompatible illuminate/support range.
  • On Laravel 11 the service provider and facade are auto-discovered; no manual registration in bootstrap/providers.php is needed. If you're upgrading an app from 10 → 11, this is the only package-side change required.
  • Look first at: the README usage block (authoritative for the exact facade/method names in this 0.x line), config/postal-code.php if the package ships one (php artisan vendor:publish --tag=postal-code-config), and src/ for the client class that actually performs the HTTP call.
  • First use case to wire up: address autofill at checkout. User types a CEP, you resolve street/neighborhood/city/state, prefill the form, and let the user correct the rest. This is the highest-value, lowest-risk integration and exercises the whole request/response path.

Implementation Patterns

Wrap the package, don't call it from controllers. Put a thin adapter around it so a provider change (or the package's 1.0 API break) doesn't ripple through your codebase:

interface PostalCodeResolver
{
    public function lookup(string $postalCode): ?Address;
}

final class PackagePostalCodeResolver implements PostalCodeResolver
{
    public function lookup(string $postalCode): ?Address
    {
        try {
            $result = PostalCode::search($this->normalize($postalCode));
        } catch (Throwable $e) {
            report($e);
            return null;
        }

        return $result ? Address::fromArray((array) $result) : null;
    }

    private function normalize(string $value): string
    {
        return preg_replace('/\D/', '', $value);
    }
}

Bind it in a service provider and inject the interface. Every other pattern below assumes this seam.

Cache aggressively. Postal codes map to stable geography — they change on the order of years, not requests. Wrap the resolver in Cache::remember("cep:{$code}", now()->addDays(30), ...). This is the single biggest win: it removes the third-party API from your latency and rate-limit budget for repeat lookups.

Validate before you call. Use a dedicated rule for the CEP format (8 digits, optionally 00000-000) and reject bad input at the FormRequest layer. Never spend an outbound HTTP request discovering that the user typed 5 characters.

Autofill endpoint pattern. Expose a small JSON route (GET /api/postal-codes/{code}) that returns a normalized address DTO, and have your frontend debounce on input. Return 204 for "unknown code" and 422 for "malformed code" so the client can distinguish retryable from not.

Bulk enrichment via queue. For backfilling addresses on existing records, dispatch a job per chunk rather than looping in a command. Combine with the cache layer so a large import doesn't hammer the upstream service.

Testing. Fake the HTTP layer (Http::fake([...])) rather than the facade wherever possible — that exercises your adapter's parsing and error handling. Add Http::preventStrayRequests() in your base test case so no test can accidentally hit the real API.

Gotchas and Tips

  • This is a 0.x package. Pre-1.0 semver means minor releases may break the public API. Pin to ^0.1.1 and read the changelog before bumping. Don't treat PostalCode::search() signatures as stable.
  • The release notes are the only compatibility signal. v0.1.1 adds Laravel 11 support and nothing else — no new features, no deprecations, no config changes. If you were already running the package on L11 via --ignore-platform-reqs or a composer.json conflict override, remove that workaround after upgrading; it will mask real conflicts later.
  • Network is a hard dependency. The lookup hits an external postal-code service. Always set a sane timeout and connect timeout in the config (or in a Guzzle client you inject), and always have a fallback path where the user can type the address manually. Treat this as a progressive enhancement, never a blocking step.
  • Normalize input on both sides. Strip masks server-side even if the frontend does it, and store the digits-only form as a canonical column so cache keys and lookups are consistent.
  • Empty results are not errors. Valid-format codes may come back with blank street/neighborhood fields (new developments, rural routes). Your DTO and UI must handle partially-populated addresses without throwing.
  • Watch for silent upstream rate limiting. If you start seeing null returns across the board, check for 429s before assuming bad data — this is why report($e) in the adapter matters. Caching plus queued backfills are the mitigation.
  • Config quirks. If the package publishes a config file, publish it before you tune it; a later vendor:publish won't overwrite an existing file, so stale config silently persists across upgrades. Verify the base URL and timeout keys actually exist in the published file rather than assuming.
  • Extension points. The interface binding above is your primary seam. Also consider a custom validation rule (so the same normalization is reused), and a Cache::lock() guard on the bulk job if you ever run more than one worker against the same upstream.
  • Re-verify on upgrade. Before bumping past 0.1.x, re-read the README and src/ — the exact response shape (array vs. object vs. DTO) is the most likely thing to shift in a minor release, and it's the thing your adapter depends on.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource