between
Requires a size between two inclusive bounds, measured by the field's own type.
between:min,maxParameters
| Parameter | Type | Description |
|---|---|---|
$min | int|float | The lower bound, inclusive. |
$max | int|float | The upper bound, inclusive. |
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 size between the given min and max (inclusive). Strings, numerics, arrays and files are evaluated in the same fashion as the size rule, so the two numbers mean characters, magnitude, element count or kilobytes depending on the field's type.
Both ends are inclusive
between:1,5 accepts 1 and accepts 5. If you need an exclusive bound there is no variant — use gt and lt, or adjust the numbers.
Same numeric trap as min and max
Without numeric or integer in the rule list, between measures string length. 'rating' => 'between:1,5' against posted input accepts any one- to five-character string, including "abcde" and "99999". Write 'rating' => 'integer|between:1,5'.
between or min plus max?
They produce the same outcome. The difference is the error message: between emits one message naming both bounds, while min:8|max:64 emits whichever bound was crossed. For a password field the separate messages are usually more helpful; for a numeric range a single message reads better.
between is not implicit, so an absent or empty field skips it. Pair it with required.
Example
<?php
use Illuminate\Support\Facades\Validator;
$rules = ['rating' => ['required', 'integer', 'between:1,5']];
foreach ([0, 1, 3, 5, 6] as $rating) {
$passes = Validator::make(['rating' => $rating], $rules)->passes();
echo $rating . ' => ' . ($passes ? 'passes' : 'FAILS') . PHP_EOL;
}
// 0 => FAILS
// 1 => passes <- lower bound is inclusive
// 3 => passes
// 5 => passes <- upper bound is inclusive
// 6 => FAILSWhen to use it
- Constraining a star rating to 1 through 5 on a review form.
- Requiring a username of 3 to 20 characters.
- Accepting between 2 and 10 poll options in a submitted array.
- Limiting an uploaded document to a 10 KB to 5 MB window.
Frequently asked questions
Is between inclusive of its bounds?
Yes, both ends are inclusive — `between:1,5` accepts 1 and 5. There is no exclusive variant; use `gt:0` and `lt:6`, or simply shift the bounds, when you need to exclude an endpoint.
Should I use between or min and max?
They validate identically, so pick on message quality. `between` produces one message naming both bounds, which reads well for numeric ranges; `min` and `max` produce a message about the specific bound crossed, which is usually more actionable for string lengths.
Why does between:1,5 accept the word "abcde"?
Because without `numeric` or `integer` in the rule list, `between` measures string length, and "abcde" is five characters. Add the type rule first: `'rating' => 'integer|between:1,5'`.
More examples
Without a numeric rule, between measures length
The first and third calls pass for the same reason: both values are five characters long. This is the single most common misuse of `between`, and it fails open rather than closed, so nothing in the application complains until bad data reaches the database.
<?php
use Illuminate\Support\Facades\Validator;
$posted = ['rating' => '99999']; // five characters
// No integer rule: strlen("99999") is 5, which is within 1..5.
var_dump(Validator::make($posted, ['rating' => 'between:1,5'])->passes());
// With integer: 99999 is compared numerically and rejected.
var_dump(Validator::make($posted, ['rating' => 'integer|between:1,5'])->passes());
// The same rule set also lets a word through:
var_dump(Validator::make(['rating' => 'abcde'], ['rating' => 'between:1,5'])->passes());
// bool(true) <- the silent bug
// bool(false)
// bool(true) <- and so does thisbetween versus min plus max — the messages differ
The check is identical; only the wording changes. `between` states the whole range, which suits a numeric field where the user needs to know both ends. `min`/`max` names the bound that was actually crossed, which is usually clearer for text length.
<?php
use Illuminate\Support\Facades\Validator;
$short = ['username' => 'ab'];
$a = Validator::make($short, ['username' => 'string|between:3,20']);
$b = Validator::make($short, ['username' => 'string|min:3|max:20']);
print_r($a->errors()->all());
print_r($b->errors()->all());
// Array
// (
// [0] => The username field must be between 3 and 20 characters.
// )
// Array
// (
// [0] => The username field must be at least 3 characters.
// )between on arrays and files
Three different meanings of `between` in one rule set: 10 to 255 characters for the question, 2 to 10 elements for the options array, and 10 KB to 5 MB for the file. The `nullable` on the attachment matters — without it, an omitted file would still be skipped, but a blank posted value converted to null would fail the `file` rule.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePollRequest extends FormRequest
{
public function rules(): array
{
return [
'question' => ['required', 'string', 'between:10,255'],
'options' => ['required', 'array', 'between:2,10'],
'options.*' => ['required', 'string', 'max:120'],
'attachment' => ['nullable', 'file', 'between:10,5120'],
];
}
}
// print_r($request->validated()['options']);
//
// Array
// (
// [0] => Yes
// [1] => No
// )
Discussion