SplFixedArrayとは
PHPの標準ライブラリ(SPL)には、さまざまなデータ構造が用意されています。その中の一つが SplFixedArray です。
SplFixedArray は、サイズが固定された配列です。通常のPHP配列は要素を自由に追加・削除できますが、SplFixedArray は作成時にサイズを決めると、後からサイズを変えられません(厳密には変更メソッドがありますが、コストがかかります)。
「制限があるなら使いにくそう…」と思うかもしれませんが、その分 メモリ使用量が少なく、アクセスが高速 というメリットがあります。要素数があらかじめ決まっているケースでは非常に有効な選択肢です。
SplFixedArrayの基本操作
作成とアクセス
<?php
// サイズ5の固定長配列を作成
$fixedArray = new SplFixedArray(5);
// 値をセット(インデックスは0始まり)
$fixedArray[0] = 'apple';
$fixedArray[1] = 'banana';
$fixedArray[2] = 'cherry';
$fixedArray[3] = 'date';
$fixedArray[4] = 'elderberry';
// 値にアクセス
echo $fixedArray[0]; // apple
echo $fixedArray[2]; // cherry
// 要素数を確認
echo $fixedArray->getSize(); // 5
echo count($fixedArray); // 5
範囲外アクセスはエラーになる
通常の配列であれば範囲外にアクセスしても単に null や警告で済むことが多いですが、SplFixedArray では 例外がスローされます。
<?php
$fixedArray = new SplFixedArray(3);
$fixedArray[0] = 'foo';
try {
echo $fixedArray[5]; // 範囲外
} catch (RuntimeException $e) {
echo 'エラー: ' . $e->getMessage();
// エラー: RuntimeException: Index invalid or out of range
}
これにより、バグを早期に発見できるという利点もあります。
通常配列との相互変換
既存の配列から SplFixedArray を作ったり、逆に通常配列に戻したりすることも簡単にできます。
<?php
// 通常配列 → SplFixedArray
$array = [10, 20, 30, 40, 50];
$fixedArray = SplFixedArray::fromArray($array);
echo $fixedArray[1]; // 20
echo $fixedArray->getSize(); // 5
// SplFixedArray → 通常配列
$backToArray = $fixedArray->toArray();
var_dump($backToArray);
// array(5) { [0]=> int(10) [1]=> int(20) ... }
fromArrayのsave_indexesオプション
fromArray() の第2引数に false を渡すと、元配列のキーを無視して詰め直してくれます。
<?php
// キーが飛んでいる配列
$sparse = [0 => 'a', 3 => 'b', 7 => 'c'];
// save_indexes: true(デフォルト)→ サイズ8になる
$fixed1 = SplFixedArray::fromArray($sparse, true);
echo $fixed1->getSize(); // 8
// save_indexes: false → サイズ3に詰める
$fixed2 = SplFixedArray::fromArray($sparse, false);
echo $fixed2->getSize(); // 3
echo $fixed2[1]; // b
イテレーションとforeachの使い方
SplFixedArray は Iterator インターフェースを実装しているため、foreach でそのまま使えます。
<?php
$fixedArray = SplFixedArray::fromArray(['red', 'green', 'blue']);
foreach ($fixedArray as $index => $value) {
echo "{$index}: {$value}\n";
}
// 0: red
// 1: green
// 2: blue
サイズの変更
固定長といっても、setSize() メソッドでサイズを変えることは可能です。ただし、既存のデータが失われる可能性があるため注意が必要です。
<?php
$fixedArray = new SplFixedArray(3);
$fixedArray[0] = 'x';
$fixedArray[1] = 'y';
$fixedArray[2] = 'z';
// サイズを5に拡張(既存データは保持される)
$fixedArray->setSize(5);
echo $fixedArray->getSize(); // 5
echo $fixedArray[0]; // x(保持)
// サイズを2に縮小(末尾のデータは失われる)
$fixedArray->setSize(2);
echo $fixedArray->getSize(); // 2
// $fixedArray[2] へのアクセスはエラー
頻繁にサイズ変更が必要な場合は、通常の配列や SplDoublyLinkedList の方が適しています。
通常配列との比較
実際にメモリ使用量を比較してみましょう。
<?php
$size = 100000;
// 通常配列
$before1 = memory_get_usage();
$normalArray = range(0, $size - 1);
$after1 = memory_get_usage();
echo '通常配列: ' . number_format($after1 - $before1) . " bytes\n";
// SplFixedArray
$before2 = memory_get_usage();
$fixedArray = new SplFixedArray($size);
for ($i = 0; $i < $size; $i++) {
$fixedArray[$i] = $i;
}
$after2 = memory_get_usage();
echo 'SplFixedArray: ' . number_format($after2 - $before2) . " bytes\n";
実行環境によって差はありますが、おおよそ以下のような傾向になります。
| 種別 | メモリ使用量の目安 |
|---|---|
| 通常配列(100,000要素) | 約8〜10 MB |
| SplFixedArray(100,000要素) | 約4〜5 MB |
SplFixedArray は通常配列の 約半分程度のメモリで済む ことが多く、大量データを扱うバッチ処理や数値計算で特に効果を発揮します。
どんなときに使うべきか
SplFixedArray が適しているのは、次のようなケースです。
- 要素数が事前にわかっているデータを扱う場合
- 大量の数値データ(行列・ベクトル計算など)を処理する場合
- メモリ使用量を抑えたいバッチ処理や長時間稼働するプロセス
逆に、要素数が動的に変わる場合や、文字列キーを使いたい場合は通常の配列の方が適しています。
まとめ
SplFixedArray の特徴を整理すると次のとおりです。
- サイズ固定の配列で、メモリ効率が高い
- 範囲外アクセス時に例外をスローするため、バグを早期発見しやすい
foreachで使えるなど、通常配列に近い使い勝手fromArray()/toArray()で相互変換も簡単
PHP標準ライブラリのデータ構造はあまり使われないことも多いですが、適切な場面で活用するとパフォーマンスの改善につながります。ぜひ一度試してみてください。