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

Nova Phone Field Laravel Package

mlsolutions/nova-phone-field

A Laravel Nova phone field for formatting and validating phone numbers in your admin panel. Adds a ready-made Nova field type so you can collect, display, and validate phone input cleanly without writing custom field logic.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a Nova-only presentation-layer component: a custom field class that renders a masked phone input and reads a hardcoded country-code → mask table from its own compiled Vue/JS. It sits cleanly in the admin-panel tier of a Laravel app and touches nothing in the domain, queue, or API layers. That narrowness is its main architectural virtue — the blast radius of adopting it is a handful of Nova resource files, and the swap-back cost is bounded. The architectural limit is equally clear: it solves how a number is typed in Nova, not how a number is stored, validated, or reconciled. Any roadmap item that depends on trustworthy phone data (SMS/WhatsApp delivery, KYC, dedupe, reporting) needs a separate server-side normalization and validation decision — realistically giggsey/libphonenumber-for-php and an E.164 column convention — which this package informs but does not settle. Treating the field as a data-quality initiative would be a category error; it is UX polish that reduces the volume of cleanup work, not one that eliminates it.

Integration feasibility. High on the happy path, conditional everywhere else. Install is a single composer require, Laravel package discovery registers the provider, and the field drops into fields() on any resource. The realistic engineering estimate is half a day to integrate, plus smoke-testing. But feasibility is gated by four undocumented facts a TPM should force into the open before committing a sprint: (1) which Nova major it targets — Nova 4 vs 5 differ in asset and component conventions and a mid-2025 release may only support one; (2) whether dist/ assets are committed or gitignored, because a package you must build yourself is a different dependency (Node toolchain, reproducibility, CI) than one you can just install; (3) whether it ships any fluent API beyond a defaultCountry()-style option, which determines how much customization lives in our code; and (4) what string actually lands in the database column, which no README will tell you and only a create-and-inspect-the-row test will answer.

Technical risk. High for unmitigated production use, and the risk is concentrated in two places, neither of them technical per se. First, licensing: the NOASSERTION designation means no declared license. For internal-only tooling that is a manageable conversation; for anything customer-facing, redistributed, or embedded in a product we sell, it is a legal-review blocker until clarified in writing. A TPM should not let this get discovered during a security or procurement review. Second, dependency health: zero stars, zero dependents, single maintainer, no published test suite. That is an accurate signal that there is no community, no third-party battle-testing, and no realistic expectation of an upstream fix for a Nova upgrade that breaks the field. Neither risk is disqualifying — the mitigation (pin the exact version, vendor the code, own the fork) is cheap precisely because the package is small and readable end-to-end in an afternoon. The genuine technical risk is subtler: the mask runs only in the browser, so the posted value is untrusted input, and a team that assumes "we added a phone field, therefore phone numbers are validated" is setting up a data-quality regression that surfaces months later in messaging failures.

Key questions. Which Nova major(s) do we run today, and is this field compatible with all of them? Are compiled assets committed, or does adoption require us to build the package ourselves? Is the license clarified, and what is our intended usage class — internal-only or shipped? Does the mask re-initialize correctly from a stored value on edit, and does it re-evaluate on paste into an empty field? Which countries in our actual customer base appear in the hardcoded lookup table, and what happens for those that don't? Do multiple phone fields on a single resource interfere with one another? And do we already have, or are we willing to build, a server-side E.164 normalize-and-validate step — because if the answer is no, the field's value is materially lower than it appears.

Integration Approach

Stack fit. Laravel + Nova, full stop. Outside that ecosystem the package has zero applicability — not a reduced value, zero — so the first gate is simply confirming the target app is on Nova and that the admin panel, not the public site, is where the phone-entry problem actually lives. If the pain is on a customer-facing signup form, this is the wrong tool and the conversation should redirect to a validation library. Within Nova, the fit is idiomatic: one field class behind a small internal helper, e.g. phone(string $name, string $attribute = 'phone') in a trait or base resource, so that all phone fields across User, Lead, Contact, Company, and order resources are constructed in exactly one place. That single indirection is the highest-leverage decision in the whole integration — it makes the eventual swap to a vendored fork or a plain Text field a one-method edit rather than a resource-by-resource audit.

Migration path. Deliberately incremental, and it should be sequenced that way. Do not migrate every resource at once. Pick one high-traffic resource where operators enter international numbers and the formatting inconsistency is a known complaint — a Lead or Contact form is typical — replace a single Text field, and run the round-trip test: create a record with +55 11 91234-5678, create another with +1 (415) 555-0132, confirm the mask switches, then inspect the database row directly rather than trusting the form's render-back. That one test answers the storage-format question and the mask-reinitialization question simultaneously. Only after that passes do you widen to the other resources through the shared helper.

Compatibility. Unverified and therefore owned by us, not by upstream. Nova 4 and Nova 5 changed asset and component conventions between majors; the package's own compatibility matrix is not published. Pin the exact version — "mlsolutions/nova-phone-field": "1.0.3", not ^ — so that a composer update cannot silently move us across a breaking upstream change, and pin it deliberately so the pin is a decision rather than an accident. Also plan for the column type: string('phone', 32) accommodates E.164 plus an extension; an integer column destroys the leading + and national leading zeros and must be corrected before the field ships, not after.

Sequencing. Three tracks, and the order matters more than the calendar. Track one (parallel, non-technical): resolve the license question and decide internal-only vs. shipped — this runs from day one and can block everything else, so starting it late is the classic failure. Track two (engineering): vendor or pin the package, build the phone() helper, integrate one field on one resource, and write the display/normalize pair — fillUsing() to strip non-digits while preserving the leading + and store E.164, displayUsing() to format on detail views. The mask is a browser convenience; the posted value is untrusted, and the normalizer is what makes downstream consumers — Twilio, tel: anchors, WhatsApp deep links, CSV exports — actually work. Track three (validation): add a server-side rule such as ['nullable', 'phone:AUTO,BR,US'] backed by libphonenumber, and reuse that identical normalizer inside any Nova filter or search built on the phone column, because admins type formatted numbers into filters while the column stores E.164 and searches will silently miss otherwise. Tracks two and three are only half-done if one ships without the other.

Operational Impact

Maintenance. Low in steady state, entirely because the codebase is small enough to read in an afternoon and fork if needed. But "low maintenance" here means low ongoing effort, not low ownership — the maintenance burden that does exist is ownership of a fork we did not intend to own. Because there is no community and no realistic expectation of upstream fixes, the TPM should assume the package's useful life ends at the next Nova major upgrade, and budget the swap then rather than discovering it in a support ticket. Keeping all field construction behind the one helper is what converts that future swap from a project into a task.

Support. Effectively none from upstream; all support is internal. That is workable for an internal admin tool used by a known population of operators, and not workable for anything with an external SLA. The practical consequence is that the team needs a debugging runbook, and the good news is it's four steps long and covers roughly ninety percent of cases: what did the network request actually post → what did fillUsing or the model mutator produce → what is in the column → what does displayUsing render. A support engineer who can walk that chain can resolve almost any "the number saved wrong" report without engineering escalation.

Scaling. The scaling dimension that matters is not request volume — the field renders in an admin browser, so load is negligible — it's country coverage and field count. Country coverage is a hardcoded lookup table in the field's frontend source; unsupported dialing codes typically fall through to a generic mask or none at all. Before rolling out to an international operator base, someone must grep that table against the actual list of countries we serve. Field count is the other axis: mobile + landline + fax on one resource is common, and mask libraries that register a global singleton frequently break in exactly this configuration, where editing one field disturbs another. Test it explicitly, and if it breaks, fall back to plain Text for the secondary numbers rather than fighting it.

Failure modes. Worth naming individually because each has a different user-visible symptom and a different mitigation. Silent truncation on paste — dynamic-mask widgets often re-evaluate only on keydown, so pasting a full international number into an empty field can leave the previous country's mask active and quietly mangle the value; test paste of both full and partial numbers. Edit-and-save corruption — if the mask isn't re-derived from the stored value on mount, opening an existing record and changing one digit mangles the number on save; this is the highest-severity failure because it damages data that was previously correct. Stale-asset ambiguity — after composer update, aggressively cached Nova JS looks exactly like "the mask doesn't work," so the first troubleshooting step is always php artisan nova:publish plus a hard refresh. Formatting-only false confidence — the mask accepts structurally plausible nonsense, and if the server-side rule is missing, garbage reaches the column looking well-formed. Filter/search miss — searching formatted input against an E.164 column returns nothing, silently, which reads to operators as data loss.

Ramp-up. Half a day of engineering to integrate is a fair estimate, and it is honest only if it includes the smoke-testing rather than just the Composer install. The tests that matter are all edge cases the README won't prompt: paste into empty, edit-existing-record-and-save, two phone fields on one form, an unsupported country code, and a filter query on the phone column. Budget the validation layer separately — the field is formatting-only, and if the roadmap genuinely needs canonical phone data, the E.164 parse-and-store work is the larger piece of the two. For the operator population, ramp-up is near-zero: it looks like a text input, and the improvement is felt rather than taught. The one thing operators should be told is to include the country code, which is exactly the kind of hint that belongs in the ->help() text on the shared helper rather than in a training doc nobody reads.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin