m-adamski/symfony-phone-number-bundle
Symfony bundle for working with phone numbers: validate, parse, and format international numbers via libphonenumber, with integrations for forms, validators, and Twig helpers. Simplifies consistent phone number handling across Symfony applications.
Architecture fit: This is a Symfony bundle, not a Laravel package. It ships a Symfony Form type (PhoneNumberType), DI extension/bundle registration, and Symfony OptionsResolver/translation wiring — none of which have a home in a Laravel application. The only transferable value is the underlying phone-number parsing/normalization library it wraps, which should be consumed directly rather than through this bundle. Treat this as an evaluation of an upstream dependency's UX layer, not of an installable capability for our stack.
Integration feasibility: Low as-is. There is no ServiceProvider, no facade, no Blade/Livewire component, and no Laravel validation rule. A viable path exists only as a re-implementation: install the underlying library, wrap it in a Rule object plus an E.164 normalizer/cast, and build the country selector in Blade or Livewire. That is a self-owned ~200-line surface, which is acceptable effort but means we would not be adopting this package in any meaningful sense.
Technical risk:
composer update with no version constraint change.Key questions:
composer.json constraints on symfony/form, symfony/translation and PHP? Will they conflict with Laravel's transitive symfony/* pins?Stack fit: Not a fit for a Laravel 10/11/12 codebase at the bundle level. Partial fit at the library level if the transitive dependency is sane. The change in 4.0.1 is confined to Symfony's translation layer, so it has zero bearing on parsing/validation correctness — reinforcing that the bundle layer is the part we would discard anyway.
Migration path: Do not install the bundle. Instead: (1) confirm the wrapped library, (2) add it directly via Composer, (3) implement App\Rules\PhoneNumber using parse()/format(E164) with a try/catch around parse failures, (4) add a phone cast or mutator for normalization at the model boundary, (5) source the country list from the library's metadata rather than from a hardcoded array, and (6) build the selector as a Blade partial or Livewire component — and explicitly decide whether country names are translated, since 4.0.1 confirms the bundle no longer does this for you.
Compatibility: Verify PHP floor against our runtime, and check that any Symfony component constraints resolve against Laravel's existing symfony/console, symfony/http-foundation, symfony/process and symfony/error-handler pins. If the underlying library has no Symfony dependency at all — the likely case — this concern disappears entirely and is the strongest argument for the direct-library route.
Sequencing:
Maintenance: Near-zero for the bundle itself because we would not depend on it. The direct-library route puts metadata currency on us: someone must own bumping the library when numbering plans change, ideally on a quarterly calendar reminder or a Dependabot rule. If we had adopted the bundle, we would be maintaining a fork to keep it working across Symfony majors.
Support: Community-only, GitHub issues, no SLA, no vendor. Response times from a single maintainer are unpredictable, and the 4.0.1 change shipped with no upgrade note — a signal that consumer-facing documentation is thin. Escalation path is "read the source."
Scaling: Negligible runtime footprint. No external services, no network calls at request time. The main cost is in-process metadata (a few MB) loaded per worker; it is effectively free under PHP-FPM but worth opcache/preload attention if we ever move to long-running workers (Octane, Swoole). Parsing is CPU-cheap relative to typical request budgets. Volume risk is not a concern; correctness risk from stale metadata is.
Failure modes:
Ramp-up: Low for a mid-level Laravel developer to use a validation rule and cast — roughly half a day including tests. Moderate if they must reason about the Symfony Form type or debug translation behavior, which is precisely the work the bundle would impose and the direct-library route avoids. The 0.5–1 day spike is the only front-loaded cost, and it also yields the metadata-freshness and license answers needed to make the build/no-build call.
How can I help you explore Laravel packages today?