What's the best way to validate numbers with comma as decimal separator?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Locale: The Best Way to Validate Numbers with Comma as a Decimal Separator in Laravel

As developers working with internationalized applications, one of the most common pain points is handling locale-specific formatting. When dealing with monetary values or measurements, users often use a comma (,) as the decimal separator in many parts of the world, while standard programming languages and database systems (like PHP and SQL) strictly expect a period (.).

In a Laravel application, if you rely on default validation rules like numeric or use Eloquent casting, this discrepancy immediately causes validation failures when user input is formatted with commas. This post will explore the best, most robust methods for validating numbers that use a comma as the decimal separator in your Laravel setup.

The Problem: Locale Mismatch in Validation

The core issue lies in the mismatch between how the user inputs data (locale-specific formatting) and how PHP/Laravel interprets numerical strings. A validation rule like 'amount' => 'numeric|min:0' expects a string containing only digits and an optional single decimal point (.). When it receives "1,234.56", it fails because the comma is not recognized as a valid numeric character by default.

We have two primary approaches to solve this: fixing the input before validation or teaching the validator how to understand the custom format.

Method 1: The Quick Fix – Pre-processing Input (The Pragmatic Approach)

For simple, one-off scenarios where you control the entire input flow, the quickest solution is to sanitize the input immediately upon receipt in your Request or Controller. This method is pragmatic but shifts the burden of cleaning data onto your application logic rather than the validation layer itself.

You can use string manipulation functions to replace the comma with a dot before passing the data to the validator.

use Illuminate\Http\Request;

class AmountRequest extends Request
{
    public function validate(Request $request)
    {
        $input = $request->input('amount');

        // Step 1: Replace comma decimal separator with a dot
        $sanitizedAmount = str_replace(',', '.', $input);

        // Step 2: Perform standard numeric validation on the sanitized string
        $rules = [
            'amount' => 'numeric|min:0',
        ];

        $validator = app('validator')->make($sanitizedAmount, $rules);

        if ($validator->fails()) {
            throw new \Illuminate\Validation\ValidationException($validator);
        }

        return true;
    }
}

Pros: Simple to implement; works immediately.
Cons: This logic is duplicated across your application (in controllers, service layers). It doesn't enforce the rule within Laravel’s native validation system, which can make code less DRY (Don't Repeat Yourself).

Method 2: The Robust Solution – Custom Validation Rules (The Architectural Approach)

For enterprise-level applications where data integrity and centralized logic are paramount, building a custom validation rule is the superior architectural choice. This approach keeps the complex formatting logic encapsulated within Laravel’s validation system.

You can create a custom rule, perhaps named french_numeric, that handles the locale conversion internally. This aligns perfectly with the philosophy of creating reusable components, much like how you structure models and relationships when working with frameworks like Laravel (see https://laravelcompany.com for deeper insights into framework architecture).

Implementing a Custom Rule

  1. Create the Rule: Define a rule that checks if the string is numeric after normalizing the input format.
  2. Register the Rule: Register this new rule in your AppServiceProvider.

For demonstration, let's imagine a hypothetical implementation where we ensure the string only contains digits and one valid decimal separator (which must be a dot after normalization).

// Example structure for defining a custom rule (simplified)
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class FrenchNumericRule implements Rule
{
    public function passes($attribute, $value)
    {
        // 1. Normalize: Replace comma with dot for validation purposes
        $normalizedValue = str_replace(',', '.', $value);

        // 2. Check if the normalized value is truly numeric (and handles empty strings)
        return is_numeric($normalizedValue) && $normalizedValue !== '';
    }

    public function message()
    {
        return 'The :attribute must be a valid number formatted with commas.';
    }
}
  1. Apply the Rule: You would then use this rule in your request validation:
$rules = [
    'amount' => ['required', 'french_numeric', 'min:0'],
];

Pros: Centralized logic; adheres to the principle of separation of concerns; makes the validation rules reusable across your entire application. This is the recommended path for maintaining clean, scalable code.

Conclusion

While pre-processing input (Method 1) offers an immediate fix, it couples formatting logic into your request handling. For robust applications, especially those dealing with internationalized data, Method 2 – building a custom validation rule – is the superior approach. It ensures that your application validates based on business rules while correctly accounting for locale-specific input formats. By leveraging Laravel’s powerful validation system and structuring your code cleanly, you ensure greater data integrity moving forward.