ysfkaya/filament-phone-input
A Filament 3 form field for international phone numbers, with country code selection, built-in validation, default country support, and configurable display and input formatting. Requires PHP 8.1+ and integrates directly into Filament forms.
Architecture fit. This is a thin, well-scoped adapter rather than a platform. It wraps two mature third-party libraries — intl-tel-input (client-side country dropdown, flags, as-you-type formatting) and propaganistas/laravel-phone (a PHP wrapper over Google's libphonenumber) — and exposes them as native Filament primitives: a form Field (PhoneInput), a table Column (PhoneColumn), an Infolist Entry (PhoneEntry), plus a PhoneInputNumberType enum. The package adds almost no business logic of its own; its value is the glue and the fluent configuration surface (~30 chainable methods mirroring intl-tel-input options). From a TPM perspective this is the ideal dependency shape: low code volume, delegated correctness, and an API that matches Filament conventions so it reads as "native" to the team.
Integration feasibility. High. composer require, two artisan commands (filament:assets, filament-phone-input:install), one translation string added to validation.php if you use validateFor. Realistic effort: a half-day spike for one developer, one to two days to pilot a single form and settle storage conventions. No migrations, no tables, no service providers to configure beyond the standard package auto-discovery, no queue or scheduler surface. The README is unusually thorough for a package of this size — it documents the full method surface, screenshots for the visual options, a troubleshooting section, and an upgrade guide, which materially reduces evaluation cost.
Technical risk. The risks are concentrated in version coupling and defaults, not in code quality:
main targets Filament 4. This divergence between badge and text is the single most important thing to verify before adoption. A UI-component package is by definition a hard version lock: a Filament major upgrade becomes a coordinated upgrade of this package or a UI regression.Number requires a country to be specified / Number does not match the provided country. Legacy data will hit this. The package's own guidance is to set defaultCountry, which is a data-quality mitigation, not a fix.validateFor and formatting depends on the libphonenumber dataset being current. That is a composer update discipline, not a code issue, but ownership must be assigned.Note also that the recorded last release date (2026-10-27) is in the future relative to any sane evaluation timeline; treat the release metadata as unverified and confirm actual release cadence on Packagist before relying on it.
Key questions.
main or the 3.x branch? Is there a documented compatibility matrix?inputNumberFormat), national, or split via countryStatePath? This decision should be made once, ahead of the pilot, not per form.disableLookup() be the org-wide default with initialCountry set explicitly?intl-tel-input via the package constraint?defaultCountry strategy?Stack fit. Laravel + PHP ^8.1 + Filament 3.x or 4.x, Livewire/Alpine on the front end. The field renders into the existing admin panel; it introduces no new persistence layer, no new tables, no runtime service. Storage is whatever Eloquent column you already point at — so the schema question is entirely yours, not the package's. The countryStatePath option cleanly supports a two-column model (phone + phone_country), with PhoneColumn::countryColumn() and PhoneEntry::countryColumn() reading it back for display.
Migration path. There is nothing to migrate from structurally, which is the package's main integration advantage:
inputNumberFormat(PhoneInputNumberType::E164)) with NATIONAL or INTERNATIONAL presentation at the edge (displayNumberFormat). E164 is the format SMS/voice providers and duplicate-detection logic expect. It also sets a column-width requirement — E164 is up to 16 characters including +, so widen to varchar(32) now rather than discovering truncation later. If you prefer split storage, adopt countryStatePath from day one; retrofitting a country column is a data-backfill project.defaultCountry per form or run a one-time enrichment pass. Expect NumberParseException noise during transition; surface it in error monitoring rather than letting users see it.validation.php before enabling validateFor, so validation failures are legible to users instead of showing raw keys.disableLookup() org-wide, with initialCountry derived from the user's stored profile country. If you want GeoIP, route it through your own endpoint via ipLookup(Closure) so it is cached, observable, and inside your privacy boundary rather than a raw third-party call.Compatibility. Pin the package major in lockstep with the Filament major and review both together. Verify filament:assets and filament-phone-input:install run idempotently in CI and in the container build — this is the most common silent breakage. Because the package constrains intl-tel-input and laravel-phone transitively, treat Composer updates as a small UI + validation regression test, not a routine patch: add a smoke test that a known-good number round-trips and that an invalid one fails validation. Also confirm the ^8.1 PHP floor against your runtime; if you are on PHP 8.3/8.4, verify the test matrix actually covers it.
Sequencing.
validateFor + translation string.PhoneColumn/PhoneEntry with displayFormat).Maintenance. Low steady-state effort but non-zero, and it must be owned rather than assumed. Two recurring chores: (a) periodic composer update to keep libphonenumber metadata current — stale numbering plans cause false validation failures on newly allocated ranges; (b) watching Filament releases, since this package cannot be upgraded independently of the admin panel's major. The single-maintainer profile means you should budget for the possibility of vendoring or forking the field; thankfully the code surface is small enough that a fork is measured in days, not months. MIT license makes that legally unencumbered.
Support. Internal support load should be modest: the README's method-by-method documentation, troubleshooting section, and upgrade guide preempt most "how do I" questions. The two predictable support tickets are validation messages (missing translation entry) and "number wouldn't save" (missing defaultCountry on legacy data). Write one internal how-to covering the format triad — inputNumberFormat (what is stored), displayNumberFormat (what is shown), focusNumberFormat (what appears on focus) — because that three-way distinction is the only genuinely confusing part of the API. Developers fluent in Filament's fluent schema will be productive in a couple of hours.
Scaling. Effectively free. Formatting and country selection are client-side; server-side validation is a CPU-negligible libphonenumber parse. The only scaling-relevant path is the default GeoIP lookup on mount: at high admin concurrency, or behind a rate-limited lookup provider, that becomes an external dependency on render latency. Disabling it or proxying it through a cached internal endpoint removes the concern entirely. No new infrastructure, no queues, no storage growth beyond the column widening.
Failure modes. Ranked by likelihood × impact:
disableLookup() + initialCountry, or a self-hosted cached lookup.NumberParseException on save, visible to users. Mitigate with defaultCountry per form plus a one-time backfill.Ramp-up. One to two days for the first developer including the spike; near-zero for subsequent developers since the API is idiomatic Filament. The real ramp-up cost is organizational, not individual: getting the team to agree on one storage format and one GeoIP policy up front is what prevents format drift, and that is a TPM-owned decision, not a code one.
How can I help you explore Laravel packages today?