min

Enforces a minimum size: characters, numeric value, array count or file kilobytes.

Signature
min:value

Parameters

ParameterTypeDescription
$valueint|floatThe minimum size. Interpreted as characters for strings, the numeric value for numbers, the element count for arrays, or kilobytes for files.

Errors

Nothing on its own; a failure surfaces as Illuminate\Validation\ValidationException when run through validate() or a form request.

The field under validation must have a minimum value. Strings, numerics, arrays and files are evaluated in the same fashion as the size rule — which is the whole story and the whole problem, because "size" means four different things:

  • String — the number of characters.
  • Numeric — the value itself, but only when the attribute also carries the numeric or integer rule.
  • Array — the element count.
  • File — the file size in kilobytes.

The trap

Every value in an HTTP request arrives as a string. Without numeric or integer alongside it, 'age' => 'min:18' measures the length of "20" — two characters — and fails. The fix is always 'age' => 'integer|min:18'. This single omission accounts for most confused reports about min, and it fails in the worst way: "100" passes because it is three characters long.

Digits versus magnitude

If you want "at least four digits" rather than "at least 4", the rule is min_digits, not min.

min is not implicit — an absent or empty field skips it entirely, so pair it with required.

Example

Example · php
<?php

use Illuminate\Support\Facades\Validator;

$data = ['age' => '20'];   // as it arrives from a form post

// No numeric rule: "20" is measured as a 2-character string.
var_dump(Validator::make($data, ['age' => 'min:18'])->passes());

// With integer, 20 is compared as a number.
var_dump(Validator::make($data, ['age' => 'integer|min:18'])->passes());

// bool(false)
// bool(true)

When to use it

  • Requiring a password of at least 8 characters.
  • Enforcing a minimum order quantity on a numeric input.
  • Rejecting an empty multi-select by demanding at least one chosen option.
  • Refusing suspiciously tiny uploads such as a zero-byte avatar.

Frequently asked questions

Why does min:18 fail on the value 20?

Because "20" arrived as a string and `min` counted its two characters. Add `integer` or `numeric` before `min` so the value is compared as a number: `'age' => 'integer|min:18'`. Without a numeric companion rule, `min` always measures string length.

Is min on a file in bytes or kilobytes?

Kilobytes. `min:1` means one kilobyte and `max:2048` means two megabytes. This matches the `size` rule's behaviour for files, so a rule like `min:1024` demands a one-megabyte file, not a one-kilobyte one.

Does min require the field to be present?

No — `min` is not an implicit rule, so an absent or empty field skips it entirely and validation passes. Combine it with `required` (or `sometimes|required`) whenever the field genuinely must be sent.

More examples

min across all four value types

The error messages differ per type — "at least 8 characters", "at least 1", "at least 2 items" — because Laravel picks the message variant from the companion rule. That is another reason to always state `string`, `integer`, `array` or `file` explicitly: without it the message is wrong as well as the check.

Example · php
<?php

use Illuminate\Support\Facades\Validator;

// String: at least 8 characters.
$a = Validator::make(['password' => 'secret'], ['password' => 'string|min:8']);

// Numeric: the value must be at least 1.
$b = Validator::make(['quantity' => 3], ['quantity' => 'integer|min:1']);

// Array: at least 2 elements.
$c = Validator::make(['tags' => ['php']], ['tags' => 'array|min:2']);

var_dump($a->passes());  // bool(false) - 6 characters
var_dump($b->passes());  // bool(true)  - 3 >= 1
var_dump($c->passes());  // bool(false) - count 1

print_r($a->errors()->all());

// Array
// (
//     [0] => The password field must be at least 8 characters.
// )

Files are measured in kilobytes

`min:1` on a file means one kilobyte, not one byte — a useful guard against truncated or zero-length uploads. Confusing the unit is a common source of rules that appear to do nothing: `min:1024` on an avatar quietly demands a one-megabyte image.

Example · php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreAvatarRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            // Between 1 KB and 2048 KB (2 MB).
            'avatar' => ['required', 'image', 'min:1', 'max:2048'],
        ];
    }
}

// echo $request->file('avatar')->getSize();   // bytes
// echo $request->file('avatar')->getSize() / 1024;   // what min/max compare

min versus min_digits

The two rules agree here but diverge on leading zeros and on magnitudes that share a digit count. When the requirement is really about formatting — a 4-digit PIN, a 10-digit phone number — `min_digits`/`max_digits` or `digits_between` express it, while `min` expresses a numeric floor.

Example · php
<?php

use Illuminate\Support\Facades\Validator;

$pin = ['pin' => 42];

// min: is the number at least 1000?
var_dump(Validator::make($pin, ['pin' => 'integer|min:1000'])->passes());

// min_digits: does the number have at least 4 digits?
var_dump(Validator::make($pin, ['pin' => 'integer|min_digits:4'])->passes());

// Both reject 42, but they say different things:
$long = ['pin' => 9999];
var_dump(Validator::make($long, ['pin' => 'integer|min:1000'])->passes());
var_dump(Validator::make($long, ['pin' => 'integer|min_digits:4'])->passes());

// bool(false)
// bool(false)
// bool(true)
// bool(true)

Discussion

  • Be the first to comment on this lesson.