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

Formatted Number Laravel Package

rimu/formatted-number

A PHP package from rimu for formatting numbers into readable, presentation-ready strings, with support for custom separators, decimals, and locale-style output. Useful for displaying prices, counts, and other numeric values consistently in Laravel or plain PHP applications.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — narrow and conditional. Despite the description ("lightweight PHP package for human-readable formatted numbers," configurable decimals, currency/percentage, reusable format definitions, "Laravel-friendly API"), the artifact is a Laravel Nova field: one PHP class extending Laravel\Nova\Fields\Field plus a compiled Vue component. There is no facade, no service provider, no publishable config, and no Blade helper. That changes the fit test entirely: this is only relevant if Nova is already your back-office surface and the gap is genuinely in resource display. It is not a formatting library for APIs, exports, Blade, Filament, or Inertia, and it does not solve input masking, validation, locale-aware currency semantics, or storage.

Integration feasibility — resolve before you plan. The gating fact is the laravel/nova and php constraint in composer.json. A last release of 2019-10-25 almost certainly pins Nova ^2.0/^3.0 and PHP 7.x. On Nova 4/5 (Inertia + Vue 3 + Vite) resolution will fail — and that failure is the cheapest, best outcome in the whole evaluation. The correct first action is not a design doc; it is composer require rimu/formatted-number --dry-run. Everything downstream is contingent on that single result. If it resolves, the install is three commands (require, optionally publish nova-assets, nova:publish) and the field class is small enough to read end to end in minutes.

Technical risk — asymmetric, and mostly ownership risk. Ranked by what a TPM should care about:

  • Unmaintained by every measure. 2 stars, 0 dependents, no release in six years, presumably no tests. No issue triage, no security response, no Stack Overflow corpus, no compatibility work past the Nova version it shipped against. Every bug becomes yours.
  • Nova 4/5 front-end breakage with form-level blast radius. A 2019 bundle built on legacy FormField/DetailField mixins and Mix conventions may fail to register, or register and throw in-browser — which breaks create/update forms for staff, not just the one column you wanted to prettify.
  • Sorting and search silently degrade. Formatted strings sort lexically: $1.2M before $900K. Nova's numeric sort/search behavior must be verified per column, not assumed.
  • Locale/format drift between the PHP class and the Vue component. If both format with different settings, index, detail, and form views can show different numbers for the same record — a trust failure that is worse than showing raw 1234567.891.
  • Write-path precision corruption. If a formatted string round-trips through an edit form, a rounded or locale-mangled value can be written back. This is the one failure mode that escapes the otherwise favorable containment.

Key questions to answer before scoping any work:

  1. Which Nova and PHP versions are we actually on, and does composer require ... --dry-run resolve?
  2. Is the requirement strictly display-only, and can we enforce that structurally (onlyOnIndex() / onlyOnDetail())?
  3. Do any of the target columns need to remain sortable or searchable?
  4. Does our in-house 30-line equivalent (a Number subclass using displayUsing() + number_format) fail any documented requirement? If not, the case for adoption collapses.
  5. Who is the named owner if we vendor it, and what is the maintenance budget per Nova upgrade?
  6. Are the users of this surface internal staff only?

Integration Approach

Stack fit. Realistic fit is Nova 3 / PHP 7.x only. If we are on Nova 2 or 3 and the decision is "make ARR, cents-stored-as-integers, quota, and row counts render consistently across ops dashboards," this is a plausible candidate. If we are on Nova 4/5, or on Filament/Inertia/Blade, it is out of scope by construction — the entire value is the Nova field contract.

The baseline comes first, not last. The right sequencing is to write the in-house equivalent before installing anything:

class FormattedNumber extends Number
{
    public function currency(string $symbol = '$', int $decimals = 2): static
    {
        return $this->displayUsing(
            fn ($v) => is_null($v) ? null : $symbol . number_format((float) $v, $decimals)
        );
    }
}

Thirty lines, zero dependencies, no upgrade exposure, and it covers essentially the entire stated value. If the requirement survives that comparison, we have a concrete gap worth scoping. If it doesn't — and it usually won't — we're done in an hour with first-party code.

Migration / adoption path (only if the baseline is insufficient). Do not composer require into production. Copy the class and component into app/Nova/Fields/ with an attribution header, add PHP tests around grouping, decimals, and separators, and record a named owner. That converts an unmaintained dependency into a small piece of first-party code we can reason about during the next Nova upgrade. The attribution obligation is trivial; the upgrade-survivability is not.

Compatibility checks, in order: composer.json constraints → field class source → resources/js/components/ and dist/ (legacy mixins vs. Inertia composition — this single fact decides feasibility) → asset registration path (vendor:publish --tag=nova-assets, nova:publish) → absence of tests.

Sequencing for the pilot:

  1. Constraint dry-run. Stop on failure.
  2. Read the field class and the Vue component to confirm what it actually does.
  3. Build the in-house Number + displayUsing() baseline.
  4. Put both on adjacent columns of one real resource — an ops/finance index showing large magnitudes.
  5. Round-trip test: seed 1234567.891, open edit, save untouched, re-read the model. Any change is a stop signal.
  6. Verify numeric sorting by clicking the header.
  7. Decide: adopt-and-vendor, or keep the baseline and delete the experiment.
  8. If adopted, centralize format rules in a config/nova-formats.php map plus a FormatsNumbers trait on the base resource, so the consistency win isn't re-implemented forty times.
  9. Write down the boundary: formatting is display-only; it does not apply to exports or API payloads.

Structural pattern to enforce regardless of vendor decision: a native Number field scoped onlyOnForms() and the formatted field scoped onlyOnIndex()/onlyOnDetail(). Two fields, one column, zero write path through the formatter. That is what preserves the containment that makes this a low-risk decision at all.

Operational Impact

Maintenance. There is no upstream to escalate to. No issue triage, no compatibility patches, no security response. Every defect and every Nova upgrade is our work. Budget it explicitly or don't adopt. Per-upgrade cost is small in absolute terms (one class, one component) but non-zero and recurring, and it lands on whoever owns the admin surface — typically one or two people.

Support. Users are internal staff; the support path is our own team. Two stars and zero dependents mean no community answers, no prior-art fixes, no Stack Overflow signal. Failure presents as "the number is blank" or "the column won't sort," which arrives as a support ticket to the team least equipped to triage a Vue bundle.

Scaling. Computational scaling is a non-issue — number_format on a render path is free. The real scaling surface is organizational: number of resources × number of formatters × number of people writing displayUsing() closures by hand. Left uncentralized, that is how you get $1.2M on one dashboard and 1234567.891 on the next, which is precisely the problem this package nominally solves. The config-map-plus-trait layer delivers the consistency benefit and survives a Nova upgrade regardless of which field class sits underneath — that is the durable asset, not the package.

Failure modes, ranked by operational consequence:

  • Form breakage on Nova 4/5 — throws in-browser, blocks create/update for staff. Highest severity; also the most likely, given the 2019 build.
  • Round-trip precision corruption — silent write-back of a rounded value. Highest severity and hardest to notice. Eliminated entirely by display-only scoping.
  • Locale/format drift between PHP and Vue — same record, two numbers. Erodes confidence in the whole dashboard faster than raw digits would. Fix: pick one rendering layer and enforce it.
  • Lexical sorting — wrong order under a right-looking header. Annoying, detectable, low severity.
  • Blank render — usually misconfiguration, occasionally the bundle. Low severity, high confusion.

Ramp-up. Using it is an hour. Owning it means understanding Nova's field lifecycle, the asset registration pipeline, and the Vue component contract well enough to fix code you didn't write during an upgrade we don't control. For a thirty-line formatter, "fork it and own it" and "write it yourself" are the same amount of work — and the second comes with no attribution obligations and no legacy constraints.

The one genuinely favorable factor: blast radius. If this breaks, internal staff see an unformatted or blank number in an admin panel. It does not touch APIs, exports, customer-facing output, or transactional data — provided display-only is enforced structurally. The moment formatting leaks into a form's write path, that containment disappears and the risk profile changes completely. Record that boundary as the decision.

Roadmap placement. Internal DX/admin backlog line item at most. It should never appear on a customer-facing roadmap. It supports one product decision — presentation consistency across operational dashboards — and explicitly does not answer "how do we accept, validate, and store monetary input." Any estimate built on the package description rather than composer.json and the field class is invalid and should be re-scoped.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
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