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

Numeric Laravel Package

laravelwebdev/numeric

LaravelWebDev Numeric adds convenient number helpers to Laravel: format, parse, and validate numeric values with a clean, framework-friendly API. Lightweight and easy to install, it keeps common numeric tasks readable and consistent across your app.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install with Composer and let Laravel's package auto-discovery register the service provider:
    composer require laravelwebdev/numeric
    
  2. Read the package README first — the whole surface area is small (a numeric validation rule and, depending on version, a thin helper). Confirm the exact namespace of the rule class before wiring it into a FormRequest, since packages of this size occasionally move the class between minor releases.
  3. Sanity-check the behaviour in tinker before adopting it, because the rule intentionally deviates from Laravel's built-in numeric:
    Validator::make(['n' => '-12.5'], ['n' => [new \LaravelWebDev\Numeric\Rules\Numeric]])->passes();
    
  4. First real use case: a form field where you want a strict, locale-independent numeric check (no exponent notation, no thousands separators, no "1.2.3"), for example an integer quantity, an account balance, or an adjustment/delta value. Prior to 1.0.1 that last case — negative deltas, refunds, temperature, offsets — was rejected; now it validates.

Implementation Patterns

As a rule object in a FormRequest (the idiomatic path):

public function rules(): array
{
    return [
        'adjustment' => ['required', new Numeric()],
        'quantity'   => ['required', 'integer', 'min:0', new Numeric()],
    ];
}

Composed with range rules. The rule answers "is this a number?", not "is this an acceptable number?". Always pair it with min/max/between when the domain is non-negative — the 1.0.1 change means -5 now passes a rule that previously blocked it:

'price' => ['required', new Numeric(), 'min:0', 'decimal:0,2'],

String-syntax registration. If the package exposes a rule alias (check the README / service provider), register it once in a ServiceProvider::boot() so 'amount' => ['numeric_strict'] works everywhere and stays greppable:

Validator::extend('numeric_strict', fn ($attribute, $value, $parameters, $validator) => /* ... */);

Normalising before validating. Form input arrives as a string; a leading +, a non-breaking space, or a thin space from a copy-paste will not validate. Normalise in prepareForValidation() rather than loosening the rule:

protected function prepareForValidation(): void
{
    $this->merge([
        'adjustment' => is_string($this->adjustment)
            ? trim(str_replace([' ', "\u{00A0}"], '', $this->adjustment))
            : $this->adjustment,
    ]);
}

Testing as a matrix. Because the accepted grammar is the entire point of the package, pin it down with a data provider that includes the negative edge cases introduced in 1.0.1:

yield 'negative int'    => ['-42', true];
yield 'negative float'  => ['-0.5', true];
yield 'negative zero'   => ['-0', true];
yield 'lone minus'      => ['-', false];
yield 'minus with gap'  => ['- 5', false];
yield 'thousands sep'   => ['1,000', false];
yield 'exponent'        => ['1e5', false];
yield 'comma decimal'   => ['1,5', false];

API/DTO layer. When the same rule guards both an HTTP endpoint and a queued job payload, extract it to a named constant or a small factory (e.g. Numeric::forSignedAmount()) so the 1.0.1 semantics are applied consistently instead of being re-declared per controller.

Gotchas and Tips

  • This is a patch release with a behavioural change. 1.0.0 → 1.0.1 widens the accepted language of the rule. Any test or downstream assumption written against 1.0.0 that asserted -1 is invalid will now fail — that is expected, but audit for it before upgrading.
  • Non-negative fields silently became permissive. Anything that previously relied on the rule as an implicit "no minus sign" guard (stock counts, page numbers, durations, percentages) now needs an explicit min:0. This is the single most likely production surprise from 1.0.1.
  • -0 and -0.0 now validate. If you (int)/(float) the input afterwards, -0 collapses to 0; if you persist the raw string to a decimal column, check how your database normalises it, because -0.00 and 0.00 may compare unequal in later reporting queries.
  • A lone - or a sign separated by whitespace must still fail. Verify this in your own suite — it is exactly the kind of edge case that a permissive regex introduced alongside negative support can accidentally allow. "- 5", "--5", "5-", and "−5" (U+2212 minus) are all worth an assertion.
  • Unicode minus. Copy-pasted values from documents/spreadsheets may carry − (U+2212) or an en dash. Decide explicitly whether to normalise in prepareForValidation() or reject; the rule will almost certainly reject, so surface a clear message rather than the default one.
  • nullable vs. empty string. Laravel's ConvertEmptyStringsToNull middleware handles '' before validation, but JSON APIs bypassing middleware can still send "". Combine with nullable and test the raw JSON path separately.
  • Cast ordering. If you cast the attribute to int/float in a FormRequest::passedValidation() or a DTO constructor before validation, you change both the type and the value the rule sees. Keep the rule on the raw input and cast afterwards.
  • Large magnitudes. The rule validates shape, not range. For bigint-scale IDs or high-precision money, pair with max: / digits_between: and store as strings, since float casting loses precision long before the rule complains.
  • Debugging failures. Laravel reports only "the field is invalid" for rule objects unless you define message(). If your rule class supports a custom message (or you add a :attribute translation key), do it — otherwise support tickets for - vs − are indistinguishable at the UI level.
  • Pin the version in composer.json ("laravelwebdev/numeric": "^1.0") and re-run your validation matrix on any future patch, given that 1.0.1 showed the package is willing to change accepted input in a patch release.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource