dniccum/phone-number
Simplify phone number handling in Laravel with validation and formatting helpers. This package provides a dedicated validation rule for international numbers, supports country codes, and helps store phone fields consistently across forms, APIs, and user profiles.
composer require, replace Text::make('phone') with PhoneNumber::make('phone'), php artisan nova:publish when assets go stale — is roughly half a day to a day including smoke tests, against one to two days of internal custom-field work. Position it as a reversible tactical shortcut, not a platform commitment.(555) 123-4567), every downstream consumer — SMS/voice providers, dedupe, search, tel: links, analytics, CRM sync — inherits a permanent parsing problem. This single behavior determines whether adoption is a net win or a data-quality debt generator.giggsey/libphonenumber-for-php or a vendor service, with this field reduced to a thin veneer over infrastructure you own anyway.Adopt when all of the following hold:
composer.json and add a CI job that installs that pinned major, runs nova:publish, and asserts the field renders with an active mask.Contact, Lead, Customer — with low to moderate volume and no messaging, dedupe, or sync dependency.tinker, and API writes are covered, not just the Nova form. If you cannot commit to this, do not adopt: you will get three definitions of "a valid phone number."Look elsewhere — or scope this down to a plain text input plus server-side validation — when:
PhoneNumberRule backed by libphonenumber plus a backfill; this package covers none of that.unsafe-eval dependency in the compiled assets.For executives — one paragraph. This is a small, MIT-licensed Laravel Nova field that gives our internal admin screens formatted, validated phone entry for roughly half a day of work instead of one to two days of custom build. It is a tactical admin-UX improvement, not a platform bet, and it is reversible. The value is only realized if we also make one product decision up front: store phone numbers in canonical E.164 form and format them only for display. If we skip that, the field will happily save human-formatted strings, and every future integration — messaging, dedupe, CRM sync, reporting — inherits a parsing problem. The ask is approval for the field swap plus the normalization rule behind it, not approval for the field alone.
For engineering — what we are and are not buying. We are buying a Nova field with client-side masking and validation, plus compiled assets delivered through Nova's publish pipeline. We are not buying a canonical phone-number library: the package description advertises a general libphonenumber-backed parser/formatter, but the repository is a Nova field, so treat any standalone rule or helper as unconfirmed until someone reads vendor/dniccum/phone-number/src/. Plan on giggsey/libphonenumber-for-php for parsing, formatting, and the shared validation rule used by form requests, imports, and APIs. Two non-negotiables: (1) a staging spike that dd()s the model after typing (555) 123-4567, because persistence behavior is the entire risk and it is undocumented; (2) normalization on the model write path, so Nova is not the only place data gets cleaned.
Decisions requested, and from whom.
| Decision | Owner | Recommendation |
|---|---|---|
| Canonical storage format | Product | E.164 at rest; human format at render only |
| Scope: masking vs. telephony-grade validation | Product | Masking + basic validation now; revisit if phone becomes a first-class asset |
| International / extension requirements | Product | Confirm single-region scope before adoption, not after first support ticket |
| Adopt, and pin Nova major + CI asset test | Engineering | Adopt on one low-traffic resource for one release cycle |
| Fork and vendor under our namespace | Engineering + Product | Decide at adoption; do not defer past the first production resource |
| Accepted vendor risk (single maintainer, 70 stars) | Product | Accept with a named owner and a documented expiry/review date |
Success looks like: one internal resource running the field for a release cycle, a phone column whose distinct-format count is 1 (E.164), no regression in paste/autofill/mobile entry, and a shared validation rule used identically by Nova and the application's write paths. Failure looks like: masked strings in the database, extensions quietly dropped, and a second source of un-normalized data arriving via CSV import.
How can I help you explore Laravel packages today?