range
Creates an array containing a sequence of numbers or characters between two boundaries.
range(string|int|float $start, string|int|float $end, int|float $step = 1): array- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$start | string|int|float | First value of the sequence. |
$end | string|int|float | Last possible value of the sequence. May be lower than start to count down. |
$stepoptional | int|float= 1 | Amount by which the sequence progresses. Always used as its absolute distance; a float with no fractional part is treated as an int. |
Return value
arrayAn array of elements from start to end inclusive. Integers unless a float is involved (then floats), or a byte sequence when both boundaries are single-character strings.
Errors
Throws a ValueError if step is 0, if step is negative while the range is increasing, or if any argument is not finite. Throws a TypeError as of PHP 8.3 if start or end is an array, object or resource.
Changelog
- PHP 8.3If both start and end are strings, a byte sequence is always produced; previously a numeric string boundary caused an implicit cast to int. E_WARNING is now emitted for empty-string boundaries, for non-numeric strings longer than one byte, and when a string is implicitly cast to int because the other boundary is numeric.
- PHP 8.3A float step with no fractional part is interpreted as an int; a ValueError is thrown when step is negative for an increasing range or is not finite; a TypeError is thrown for array, object or resource boundaries.
range builds a filled array in one call: range(1, 5) gives [1, 2, 3, 4, 5], range('a', 'e') gives the letters, and range(10, 0, 2) counts down in twos. Both boundaries are inclusive when the step lands on them.
When to reach for it
Pagination links, hour or minute pickers, year dropdowns, seeding test data with array_map, generating letter buckets for an A–Z index, or building a chart's x-axis. It is also the shortest way to produce a list you immediately shuffle or sample from.
What trips people up
PHP 8.3 tightened the rules considerably. A negative step with an ascending range is now a ValueError rather than a silently accepted argument — to count down, put the larger value in start and keep step positive. Two string boundaries now always produce a byte range, so range('1', '5') behaves differently than it did before 8.3, and multi-byte or empty string boundaries raise warnings.
Float steps hit floating-point rounding: range(0, 1, 0.1) may not contain an exact 0.7. Compare with a tolerance, or work in integers and divide afterwards. Finally, the whole array is materialised in memory — a million-element range costs real megabytes, so prefer a for loop or a generator for large spans.
Example
When to use it
- Build the option list for a year or hour dropdown, e.g. range(date('Y'), 1990).
- Generate a page-number strip around the current page for pagination links.
- Seed test fixtures with array_map over range(1, 50) instead of writing a loop.
Frequently asked questions
How do I create a descending range in PHP?
Put the larger number first and keep the step positive: range(10, 1) or range(100, 0, 10). Passing a negative step to an ascending range throws a ValueError as of PHP 8.3.
Is the end value included in range?
Yes, when the step lands exactly on it. range(0, 10, 3) stops at 9 because 12 would overshoot the boundary.
Why does range('a', 'z') not include uppercase letters?
A string range walks byte values, and in ASCII the uppercase letters sit before the lowercase ones. Use array_merge(range('A', 'Z'), range('a', 'z')) to get both.
More examples
Counting down and the 8.3 ValueError
Swapping the boundaries is the supported way to descend and prints 5 4 3 2 1. A negative step on an ascending range and a zero step both throw ValueError in PHP 8.3 and later, so the two catch blocks print their messages instead of returning an array.
<?php
echo implode(' ', range(5, 1)), "\n";
try {
range(1, 5, -1);
} catch (ValueError $e) {
echo 'ValueError: ', $e->getMessage(), "\n";
}
try {
range(1, 5, 0);
} catch (ValueError $e) {
echo 'ValueError: ', $e->getMessage(), "\n";
}Float steps and rounding
Quarter steps are exact in binary floating point, so the first range is clean. The 0.1 step is not: the strict in_array check for 0.7 prints false because the accumulated value is 0.7000000000000001, and only after rounding does the second check print true.
<?php
$floats = range(0, 1, 0.25);
print_r($floats);
$tenths = range(0, 1, 0.1);
var_dump(in_array(0.7, $tenths, true));
var_dump(in_array(0.7, array_map(fn($f) => round($f, 1), $tenths), true));
Discussion