range — 連番配列を生成する

PHP
  • カテゴリ: PHP
  • 掲載バージョン: PHP 8.4
  • 名前空間 / FQCN / コマンド: range(グローバル関数)
  • 関連: array_fill / array_map / array_filter / array_keys / DatePeriod
  • 変更履歴: PHP 8系で引数検証が厳格化。step0 の場合は ValueError 例外に(従来は警告)。

要点(TL;DR)

  • 目的:開始値から終了値まで、一定刻みの値を配列で生成する
  • 最小コード:$xs = range(1, 5); // [1,2,3,4,5]
  • 罠:
    • 巨大レンジはメモリ圧迫(配列は全要素を保持)
    • 浮動小数の刻みは誤差で終端が合わないことがある
    • 文字レンジは単一バイト前提'A'..'Z'はOK、マルチバイト不可)

概要

range() は数値や英字のシーケンスをまとめて作る関数です。ループを書かずに「1〜100」や「A〜Z」を生成でき、テストデータ作成・ページネーション・ID分割などで便利です。一方で返り値が配列のため大きな範囲生成はメモリを消費します。

構文 / シグネチャ

array range(int|float|string $start, int|float|string $end, int|float $step = 1)
  • 引数(表)
引数必須既定値説明
$startint|float|string開始値。文字の場合は単一バイト文字として扱う
$endint|float|string終了値(両端含む
$stepint|float1刻み幅。負数で降順可。0は不可
  • 戻り値array(0始まりの数値キー、要素は $start から $end までの値)
  • 例外/副作用
    • ValueError: $step === 0 の場合
    • 浮動小数の刻みでは丸め誤差に注意
    • 文字列レンジは ASCII 的挙動、マルチバイト非対応

使用例

最小例

<?php
$ints = range(1, 5);         // [1,2,3,4,5]
$desc = range(5, 1, -2);     // [5,3,1]
$alph = range('A', 'F');     // ['A','B','C','D','E','F']

var_dump($ints, $desc, $alph);

実務例:バルク処理を固定件数で分割

<?php

/**
 * 大量レコードを1,000件ずつ処理する例
 */
$total = 125_000;
$chunk = 1_000;

foreach (range(0, $total - 1, $chunk) as $offset) {
    // ここで DB から $chunk 件を取得して処理
    // SELECT ... LIMIT $chunk OFFSET $offset
    processChunk($offset, $chunk);
}

function processChunk(int $offset, int $limit): void
{
    // 実処理(例外処理は省略)
    // ...
}

実務例:日付配列を生成(小規模)

<?php
$start = new DateTimeImmutable('2024-01-01');
$days  = array_map(
    fn($i) => $start->modify("+$i day")->format('Y-m-d'),
    range(0, 6) // 7日分
);
// ['2024-01-01','2024-01-02', ... '2024-01-07']

日付の大レンジは DatePeriod の利用を検討。

よくある落とし穴・注意

  • メモリ使用range(1, 10_000_000) のような大きな範囲は一括配列で保持され、メモリ不足の原因に。
  • 浮動小数の誤差range(0, 1, 0.1) などは誤差で終端が合わないことがある。厳密さが必要なら整数で管理し、必要時にスケーリング。
  • 文字列レンジの制約range('あ','お') は意図通り動かない(単一バイト前提)。英数字のみを想定。
  • step=0 は例外ValueError が投げられる。降順は負の step を使う。

代替・関連APIとの比較

  • for ループ:超大きい範囲は for で逐次処理(メモリ節約)。
  • Generator(yield:必要なときだけ値を生成でき、遅延評価でメモリ効率が良い。
  • DatePeriod:日付レンジは専用クラスが安全・高速。
  • array_fill / array_maprange() の結果に対して値を変換・埋める用途で組み合わせる。

Generator 例(メモリ効率)

<?php
function xrange(int $start, int $end, int $step = 1): Generator
{
    if ($step === 0) {
        throw new ValueError('step must not be 0');
    }
    if (($start <= $end && $step < 0) || ($start >= $end && $step > 0)) {
        return; // 空(方向が合わない)
    }
    for ($i = $start; ($step > 0) ? $i <= $end : $i >= $end; $i += $step) {
        yield $i;
    }
}

// 例: 巨大範囲でも低メモリ
foreach (xrange(1, 10_000_000) as $i) {
    // 逐次処理
}

テスト例(Pest)

<?php

it('generates inclusive integer ranges', function () {
    expect(range(1, 3))->toBe([1, 2, 3]);
});

it('supports descending with negative step', function () {
    expect(range(5, 1, -2))->toBe([5, 3, 1]);
});

it('generates alphabet ranges', function () {
    expect(range('A', 'C'))->toBe(['A', 'B', 'C']);
});

it('throws on step zero', function () {
    $fn = fn() => range(1, 5, 0);
    expect($fn)->toThrow(ValueError::class);
});

トラブルシュート(エラー別)

症状/エラー原因対処
Allowed memory size exhausted範囲が大きすぎ配列が巨大化分割処理に切替、Generator/for を使用
期待した終端にならない(小数)浮動小数誤差整数でスケールして管理(例:小数第1位なら×10)
日本語文字レンジが変単一バイト前提の挙動マルチバイトは不可。必要なら独自ロジック
ValueError: step must not be 0step=01 以上(または負値で降順)を指定

参考リンク

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする