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

Laravel Format Laravel Package

jeroennoten/laravel-format

Format values in Laravel the easy way: helpers and Blade directives for dates, numbers, currency, and more, with configurable presets and locale-aware output, so your views stay clean and consistent.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you composer require anything, run the resolution spike. This package's newest published release is a one-line compatibility declaration for Laravel 5.4 (January 2017). That means the composer.json almost certainly pins illuminate/support to the ~5.4 family with a PHP floor in the 5.6.4 range. On Laravel 8+ the install does not degrade — it fails dependency resolution outright. Spend 15 minutes in a scratch container against your real target version and capture the exact Composer error before you budget any engineering time. If it fails, stop reading the rest of this section and go to Gotchas and Tips for the fork decision.

If you are in a 5.4/5.5 app, the integration is genuinely small:

  1. composer require jeroennoten/laravel-format
  2. Register the service provider in config/app.php (or confirm package auto-discovery is not available on 5.4 — you will likely add it manually to providers).
  3. php artisan vendor:publish --provider="JeroenNoten\LaravelFormat\..." to get the config file out. Publish it. Never rely on the vendor default for presets; you want your formatting decisions in your repo, reviewable in a diff.
  4. Read the source before the docs. There is effectively no README of substance here — the description is marketing copy, not API reference. Open src/, find the service provider, follow what it binds into the container, and identify the facade's accessor. That is a 20-minute job and it will tell you more than any external write-up.

First use case: get formatting out of Blade. The reason to adopt this at all is that {{ number_format($invoice->total, 2) }} scattered across forty views is unmaintainable — the day finance asks for thousands separators or a currency symbol, you are doing a grep-and-replace across templates. So the first thing you do is define one preset for your most repeated format (money is the usual candidate) in the published config, and replace three real call sites. Not forty. Three, in one screen, so you can eyeball the before/after.

// config/format.php — shape will vary, check the vendor default
'presets' => [
    'money' => ['decimals' => 2, 'decimal_point' => '.', 'thousands_sep' => ','],
    'short_date' => ['format' => 'd M Y'],
],
{{-- before --}}
{{ number_format($invoice->total, 2, '.', ',') }}

{{-- after --}}
{{ format($invoice->total, 'money') }}

Confirm the facade alias resolves in tinker (app()->make('format') or whatever the binding key is) before you go further. A facade that fails to resolve inside a queued job or an artisan command — but works fine in HTTP — is a classic sign the provider is registered conditionally or the alias is colliding. Find that out on day one, not in production.

Implementation Patterns

Wrap it behind a first-party interface, immediately. This is not optional given the maintenance signal. Create a ValueFormatter contract in your own namespace, bind the package to it in a service provider, and inject the contract everywhere. The package becomes an implementation detail you can replace without touching a call site. This costs you two files and converts an unbounded dependency risk into a bounded one.

// app/Support/Formatting/ValueFormatter.php
interface ValueFormatter
{
    public function number($value, string $preset = 'default'): string;
    public function date($value, string $preset = 'short'): string;
}

The adapter is where you also normalise the awkward edges — null input, Carbon vs string dates, numeric strings from the database. Do that in one place rather than at every call site.

Presets are the actual feature; treat them as your formatting vocabulary. The package's value is not number_format in a wrapper — it is that formats become named and centralised. Give them domain names (invoice_money, report_date, dashboard_compact), not structural names (two_decimals). When the finance team changes the presentation, the change is one config edit and a reviewable PR, and the name still reads correctly at the call site.

Format at the presentation boundary only. Formatting belongs in Blade, in a presenter, or in an API resource — never in a model accessor, never in a repository, never in a domain object. If you format in an accessor, your values are strings before they reach business logic, and $invoice->total * 1.2 becomes a bug you find in week nine. The rule: the database layer holds raw values; the view layer holds formatted strings; nothing else crosses the boundary.

For controllers and API responses, decide explicitly. API responses should almost always ship raw numeric values plus a separate formatted field, not formatted strings alone — clients that need to do arithmetic will thank you, and clients that render will ignore the extra key. Do not let formatting leak into your JSON contract in a way you cannot undo.

Extend via the container, never by editing vendor/. The description advertises custom formatters and Laravel bindings; use them. Bind your extension in AppServiceProvider, and if a preset needs behaviour the config cannot express, implement a custom formatter class and register it. Anything you patch into vendor/ disappears on the next composer install and will not appear in a code review.

Use it for composition, not just substitution. The chainable API is worth using where you genuinely have a pipeline — e.g. trimming a label, then truncating it, then applying a suffix for a compact dashboard widget. Where you have a single transformation, a direct call is clearer; chains that always have length one are noise.

Test the presets, not just the call sites. One test per named preset that asserts the exact output string for a representative input. That is a cheap regression net for the day config gets "tidied up" and the decimal separator quietly changes. Keep those tests alongside assertions on the raw values in your domain tests, so a formatting change never masquerades as a data change.

Backfill opportunistically, not as a project. Replace format calls as you touch a screen. A package-wide sweep of a 5.4 codebase is a multi-day diff with high regression risk and no functional payoff — the exact kind of work that gets reverted.

Gotchas and Tips

The compatibility band is narrow and unverified at the edges. 5.4 is supported by this release. 5.5 is plausible but untested by anyone upstream. 6 through 7 likely fail resolution. 8 and above will not install. Verify the installed version actually works in a job and an artisan command, not just in a browser — older packages frequently resolve the facade correctly in HTTP and fail elsewhere due to provider registration order.

config:cache will break closures. If your published config (or the vendor default) contains a closure, php artisan config:cache fails or silently produces a broken cache, and the failure looks like an unrelated formatting bug. Keep every preset a plain array of scalars. If you need a closure-based formatter, it belongs in a class, bound in the container.

Locale is the number-one source of "why does it look wrong". Laravel's number_format-style helpers are not locale-aware — they take explicit separators. If your app is set to de or fr and you assumed setLocale() would change decimal commas, it will not. Conversely, date formatting flows through Carbon and is timezone-sensitive: a date rendered at 23:30 UTC can display as the next day in a Europe/Amsterdam app. Decide per preset whether a date is a timestamp (timezone-apply) or a calendar date (timezone-ignore), and encode that decision in the preset name so it cannot be gotten wrong at the call site.

Never format money into a float and back. number_format returns a string; if anything downstream parses it, you have lost precision on large totals and introduced a thousands-separator bug for free. Formatting is the last step, and the formatted string is a dead end — it goes to a view and nowhere else.

Floating point, generally. Even with correct separation, 0.1 + 0.2 problems survive formatting. If amounts are monetary, store integer cents and format at the edge.

Facade alias collisions. A Format facade in a 5.4-era app that also pulls in another helper package is a realistic conflict. Register the alias explicitly in config/app.php under a name you control rather than relying on whatever the provider registers, and if you cannot, resolve through app()->make() in the adapter and skip the facade entirely.

Blade directive changes need view:clear. If the package registers custom Blade directives (likely, given "simple integration with Blade templates"), edits to config or to the directive implementation will not appear until compiled views are cleared. Check that first when output looks stale — it will save you an hour of debugging a non-bug.

Debugging resolution order. When output is wrong, work backwards: (1) what does the raw value look like — dump it in the controller; (2) what preset name was actually passed (typos in a string-keyed config fail silently to a default, which is the most common cause of "it ignored my config"); (3) is the config cached; (4) is the facade resolving to the class you think (dd(get_class(app()->make('format')))). Ninety percent of issues are step 2.

Unknown preset names likely fall back rather than throw. That is convenient in development and dangerous in production — a typo'd preset renders with the default format and nobody notices. If the package does not offer a strict mode, wrap preset resolution in your adapter and throw on an unknown key. Fail loudly at the boundary where you can still fix it.

Lock the dependency and mirror it. With a package this dormant, a transitive dependency moving under you is a real Friday-afternoon build break. Commit composer.lock, and if the app matters, serve Composer from a private mirror or a path/vcs repository pointing at a vendored copy. Do not let a composer update on an unrelated branch silently alter formatting behaviour.

Budget for the fork before you need it. Confirm the MIT license permits an internal fork (it does), then write down an expiry date for the exception. The realistic end state is that your team owns this code: patching the illuminate/* constraint yourself when the host app upgrades, or replacing the adapter. Put that in the same quarter as the framework upgrade, not after it — a formatting helper stranded behind an EOL framework constraint is a two-hour fix now and a two-week archeology exercise in eighteen months.

Onboarding cost is the stack, not the package. The package is a few hours to learn. Laravel 5.4 idioms and PHP 5.6-era conventions are knowledge most of your team no longer holds and will not build by working here. Weigh that against the cost of the framework upgrade that removes the dependency entirely — for a formatting helper, "delete it and use number_format behind one adapter" is a legitimate competing option and often the cheaper one.

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.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk