【PHP8.x】RecursiveArrayIterator::CHILD_ARRAYS_ONLY定数の使い方
CHILD_ARRAYS_ONLY定数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『CHILD_ARRAYS_ONLY定数は、多次元配列を再帰的に処理するためのRecursiveArrayIteratorクラスの動作を制御するフラグを表す定数です。この定数をRecursiveArrayIteratorのインスタンス生成時に指定すると、再帰の対象となる子要素の判定基準が変更されます。具体的には、hasChildrenメソッドが、現在の要素が純粋な配列である場合にのみtrueを返すようになります。この結果、イテレータは配列である要素に対してのみ再帰的に処理を行い、下位の階層へ進みます。このフラグを指定しない場合のデフォルトの動作では、hasChildrenメソッドは配列だけでなく、ArrayAccessインターフェースを実装したオブジェクトも子要素を持つと判断します。したがって、CHILD_ARRAYS_ONLYは、処理対象を厳密に配列のみに限定し、オブジェクトを子要素として扱いたくない場合に非常に有効です。この定数は、RecursiveArrayIteratorのコンストラクタの第2引数である$flagsに渡して使用します。』
構文(syntax)
1<?php 2 3$data = [ 4 'associative_array' => ['a' => 'apple', 'b' => 'banana'], 5 'numeric_array' => ['cherry', 'orange'], 6 'scalar_value' => 'lemon' 7]; 8 9// CHILD_ARRAYS_ONLY フラグを指定すると、連想配列のみが子要素として再帰的に処理されます。 10// この例では 'numeric_array' は無視されます。 11$iterator = new RecursiveIteratorIterator( 12 new RecursiveArrayIterator($data, RecursiveArrayIterator::CHILD_ARRAYS_ONLY) 13); 14 15foreach ($iterator as $key => $value) { 16 echo "{$key}: {$value}" . PHP_EOL; 17} 18 19?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
int
RecursiveArrayIterator::CHILD_ARRAYS_ONLY は、イテレータが子配列のみを走査するように設定するための整数定数です。
サンプルコード
RecursiveArrayIterator::CHILD_ARRAYS_ONLY の使い方
1<?php 2 3/** 4 * イテレータ可能 (Traversable) なオブジェクトの例。 5 * RecursiveArrayIterator が、配列内に存在するこのようなオブジェクトを 6 * 子要素として扱うかどうかの違いを示すために使用します。 7 */ 8class MyTraversableObject implements IteratorAggregate 9{ 10 private array $data; 11 12 public function __construct(array $data) 13 { 14 $this->data = $data; 15 } 16 17 /** 18 * オブジェクトの内部データをイテレートするためのArrayIteratorを返します。 19 */ 20 public function getIterator(): Traversable 21 { 22 return new ArrayIterator($this->data); 23 } 24} 25 26/** 27 * RecursiveArrayIterator::CHILD_ARRAYS_ONLY フラグの使用例を示す関数です。 28 * 29 * この関数は、多次元配列(Traversableオブジェクトを含む)を再帰的に走査し、 30 * 各要素とその深さ(ネストレベル)を出力します。 31 * RecursiveArrayIterator::CHILD_ARRAYS_ONLY フラグの有無によって、 32 * 配列内のTraversableオブジェクトの扱いがどのように変わるかを示します。 33 * 34 * @param array $data 処理する多次元配列。Traversableオブジェクトを含めることができます。 35 * @param bool $useChildArraysOnly CHILD_ARRAYS_ONLY フラグを適用するかどうか。 36 */ 37function demonstrateChildArraysOnly(array $data, bool $useChildArraysOnly): void 38{ 39 // フラグを設定。$useChildArraysOnly が true なら CHILD_ARRAYS_ONLY を使用。 40 // そうでなければデフォルトのフラグ (0) を使用。 41 $flags = $useChildArraysOnly ? RecursiveArrayIterator::CHILD_ARRAYS_ONLY : 0; 42 43 // RecursiveArrayIterator をインスタンス化し、配列と設定したフラグを渡します。 44 $arrayIterator = new RecursiveArrayIterator($data, $flags); 45 46 // RecursiveIteratorIterator を使用して、配列を再帰的に走査します。 47 // RecursiveIteratorIterator::SELF_FIRST は、親要素を先に処理することを意味します。 48 $iterator = new RecursiveIteratorIterator($arrayIterator, RecursiveIteratorIterator::SELF_FIRST); 49 50 echo "--- " . ($useChildArraysOnly ? "CHILD_ARRAYS_ONLY フラグを使用" : "フラグなし") . " ---\n"; 51 52 // イテレータをループし、各要素とその情報を出力します。 53 foreach ($iterator as $key => $value) { 54 // 現在のイテレータの深さを取得し、インデントとして使用します。 55 // 深さが増えるほど、ネストが深いことを示します。 56 $indent = str_repeat(' ', $iterator->getDepth()); 57 58 // 値の型に応じて表示を調整します。 59 $displayValue = ''; 60 if (is_array($value)) { 61 $displayValue = 'Array'; 62 } elseif (is_object($value)) { 63 $displayValue = 'Object (' . get_class($value) . ')'; 64 } else { 65 $displayValue = $value; 66 } 67 68 echo $indent . "深さ: " . $iterator->getDepth() . ", キー: " . $key . ", 値: " . $displayValue . "\n"; 69 } 70 echo "\n"; 71} 72 73// サンプルデータ: スカラー値、配列、およびTraversableオブジェクトを含む多次元配列。 74$sampleDataWithTraversable = [ 75 'level1_scalar' => '文字列データ', 76 'level1_traversable_obj' => new MyTraversableObject([ 77 'sub_obj_item1' => 'オブジェクト内の値1', 78 'sub_obj_item2' => 'オブジェクト内の値2' 79 ]), 80 'level1_array' => [ 81 'sub_arr_item1' => '配列内の値1', 82 'sub_arr_item2' => new MyTraversableObject([ 83 'deep_obj_item1' => '深いオブジェクト内の値' 84 ]), 85 'sub_arr_item3' => '配列内の値3', 86 ], 87 'level1_another_scalar' => 12345, 88]; 89 90// 1. CHILD_ARRAYS_ONLY フラグなしでイテレータを実行します。 91// この場合、RecursiveArrayIterator は配列だけでなく、配列内の Traversable オブジェクトも 92// 再帰的に走査しようとします。 93demonstrateChildArraysOnly($sampleDataWithTraversable, false); 94 95// 2. CHILD_ARRAYS_ONLY フラグを使用してイテレータを実行します。 96// この場合、RecursiveArrayIterator は「子」として配列のみを再帰の対象とします。 97// 配列内の Traversable オブジェクトは、それ以上深く走査されなくなります。 98demonstrateChildArraysOnly($sampleDataWithTraversable, true); 99
PHP 8のRecursiveArrayIterator::CHILD_ARRAYS_ONLYは、多次元配列を再帰的に走査するRecursiveArrayIteratorクラスで使用される定数です。この定数は引数を取らず、int型の値を返し、イテレータの挙動を制御するフラグとして機能します。
このサンプルコードは、配列とTraversableインターフェースを実装したオブジェクト(MyTraversableObject)が混在する多次元データを、RecursiveArrayIteratorとRecursiveIteratorIteratorを使って再帰的に走査する方法を示しています。特に、CHILD_ARRAYS_ONLYフラグの有無によって、配列内のTraversableオブジェクトの扱いがどのように変わるかを比較しています。
demonstrateChildArraysOnly関数をCHILD_ARRAYS_ONLYフラグなしで実行すると、RecursiveArrayIteratorは配列だけでなく、配列内に含まれるTraversableオブジェクトも子要素として認識し、その内部データまで深く再帰的に走査します。これにより、オブジェクト内のデータも詳細に表示されます。
対照的に、CHILD_ARRAYS_ONLYフラグを指定して実行すると、RecursiveArrayIteratorは配列のみを再帰的な走査の対象とします。この場合、配列内にTraversableオブジェクトが存在しても、それらは単一のオブジェクトとして扱われ、その内部データは深く走査されません。つまり、再帰の対象を配列構造に限定し、Traversableオブジェクトはそれ以上展開されないという挙動になります。このフラグにより、再帰処理の範囲を制御し、必要な部分のみを効率的に走査することが可能になります。
このRecursiveArrayIterator::CHILD_ARRAYS_ONLY定数は、多次元配列を再帰的に処理する際の挙動を制御します。このフラグを使うと、RecursiveArrayIteratorは「配列」の中に含まれる「別の配列」だけを深く走査するようになります。一方、このフラグを設定しない場合は、配列に含まれるTraversableインターフェースを実装したオブジェクトも再帰の対象となります。
初心者の方は、この違いをしっかり理解することが重要です。この定数を使わないと、配列内のオブジェクトが持つ内部データまで意図せず深く走査される可能性があり、処理性能やメモリ使用量に影響を与えることがあります。期待する結果を得るためには、対象とするデータ構造が配列なのか、イテレータ可能なオブジェクトなのかを事前に把握し、適切にフラグを設定してください。これにより、効率的で安全なデータ処理が可能になります。
RecursiveArrayIterator::CHILD_ARRAYS_ONLYで配列のみを走査する
1<?php 2 3/** 4 * RecursiveArrayIterator::CHILD_ARRAYS_ONLY の使い方を示すサンプルコード。 5 * 6 * この定数は、RecursiveArrayIterator と RecursiveIteratorIterator を使って 7 * 多次元配列を走査する際に、子要素が配列である場合にのみ再帰的に深掘りすることを制御します。 8 * これにより、スカラー値やオブジェクトなどの非配列の子要素は、 9 * それ以上再帰的に探索されることなく、現在のレベルで処理が停止します。 10 * 11 * 「array_only」というキーワードは、配列から特定のキーを持つ要素だけを抽出する 12 * Laravelのヘルパー関数などを連想させますが、このCHILD_ARRAYS_ONLY定数は、 13 * 配列の「種類」に着目し、多次元配列の中から「配列」という構造を持つ子要素のみを 14 * 効率的に深掘りして探索・処理したい場合に特に有用です。 15 */ 16function demonstrateChildArraysOnly(): void 17{ 18 // サンプルとなる多次元配列を定義します。 19 // さまざまな型の要素を含めることで、CHILD_ARRAYS_ONLY の効果を明確にします。 20 $data = [ 21 'users' => [ 22 ['id' => 1, 'name' => 'Alice'], 23 ['id' => 2, 'name' => 'Bob', 'status' => 'active'], 24 'count' => 2, // ユーザーリスト内のスカラー値 25 ], 26 'products' => [ 27 ['id' => 101, 'name' => 'Laptop', 'price' => 1200], 28 ['id' => 102, 'name' => 'Mouse', 'price' => 25], 29 ], 30 'metadata' => [ 31 'version' => '1.0', 32 'last_updated' => '2023-10-27', 33 'history' => (object)['editor' => 'system'] // ユーザー定義オブジェクト 34 ], 35 'summary' => 'This is a summary string.', // トップレベルのスカラー値 36 'timestamp' => new DateTime(), // トップレベルの組み込みオブジェクト 37 ]; 38 39 echo "--- CHILD_ARRAYS_ONLY を使用しない場合(デフォルトの挙動)---\n"; 40 echo " - すべての子要素(配列、スカラー値、オブジェクトなど)を再帰的に走査しようとします。\n"; 41 echo " - ただし、オブジェクトが自身でイテレーターを実装していない限り、その内部には深入りしません。\n"; 42 43 // RecursiveArrayIterator を初期化(デフォルトモード) 44 $iterator = new RecursiveArrayIterator($data); 45 // RecursiveIteratorIterator を初期化。RecursiveArrayIteratorのモードを適用します。 46 // RecursiveIteratorIterator::SELF_FIRST は、現在の要素を処理してから子要素を処理するモードです。 47 $recursiveIterator = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST); 48 49 // イテレーションして、キーと値、現在の深さを出力 50 foreach ($recursiveIterator as $key => $value) { 51 // 現在の深さに応じてインデントを調整 52 $indent = str_repeat(' ', $recursiveIterator->getDepth()); 53 // 値が配列かオブジェクトかスカラー値かによって表示を調整 54 $displayValue = is_array($value) ? '[Array]' : (is_object($value) ? get_class($value) : (string)$value); 55 echo sprintf("%sDepth: %d, Key: %s, Value: %s\n", $indent, $recursiveIterator->getDepth(), $key, $displayValue); 56 } 57 echo "\n"; 58 59 echo "--- RecursiveArrayIterator::CHILD_ARRAYS_ONLY を使用する場合 ---\n"; 60 echo " - RecursiveArrayIterator::CHILD_ARRAYS_ONLY を指定すると、\n"; 61 echo " 子要素が配列である場合にのみRecursiveIteratorIteratorが再帰的に深掘りします。\n"; 62 echo " - スカラー値やオブジェクトは、それ自身が配列ではないため、再帰の対象外となり、\n"; 63 echo " その要素が属するレベルで処理が停止します。\n"; 64 65 // RecursiveArrayIterator を CHILD_ARRAYS_ONLY フラグ付きで初期化 66 $childArraysOnlyIterator = new RecursiveArrayIterator($data, RecursiveArrayIterator::CHILD_ARRAYS_ONLY); 67 // RecursiveIteratorIterator を初期化。CHILD_ARRAYS_ONLY フラグが適用され、挙動が変化します。 68 $recursiveChildArraysOnlyIterator = new RecursiveIteratorIterator($childArraysOnlyIterator, RecursiveIteratorIterator::SELF_FIRST); 69 70 // イテレーションして、キーと値、現在の深さを出力 71 foreach ($recursiveChildArraysOnlyIterator as $key => $value) { 72 $indent = str_repeat(' ', $recursiveChildArraysOnlyIterator->getDepth()); 73 $displayValue = is_array($value) ? '[Array]' : (is_object($value) ? get_class($value) : (string)$value); 74 echo sprintf("%sDepth: %d, Key: %s, Value: %s\n", $indent, $recursiveChildArraysOnlyIterator->getDepth(), $key, $displayValue); 75 } 76 echo "\n"; 77 78 echo "--- CHILD_ARRAYS_ONLY の効果のまとめ ---\n"; 79 echo " - CHILD_ARRAYS_ONLY を使うと、多次元配列の中から、\n"; 80 echo " ネストされた「配列としての構造」のみを効率的に探索・処理できます。\n"; 81 echo " - 例えば、設定ファイルやデータ構造の中で、特定のレコードのリスト(配列の配列)や\n"; 82 echo " 設定グループ(キーと値のペアからなる配列)だけを対象としたい場合に有用です。\n"; 83} 84 85// 関数を実行してデモンストレーションを開始 86demonstrateChildArraysOnly();
PHP 8のRecursiveArrayIterator::CHILD_ARRAYS_ONLYは、多次元配列を効率的に走査する際に利用される定数で、戻り値は整数型です。この定数をRecursiveArrayIteratorおよびRecursiveIteratorIteratorと共に使用すると、配列の子要素が「配列」である場合にのみ、その配列の中へさらに深く再帰的に探索するよう挙動を制御します。これにより、文字列や数値などのスカラー値や、配列ではないオブジェクトは、それ以上深掘りされることなく、現在の階層で処理が停止します。
サンプルコードでは、この定数を使用しない場合(デフォルトの挙動)と使用する場合を比較し、その効果を具体的に示しています。デフォルトでは、オブジェクトなども再帰の対象と見なされ処理されますが、CHILD_ARRAYS_ONLYを指定することで、純粋な配列構造だけが深掘りされ、より焦点を絞った走査が可能になります。「array_only」というキーワードはLaravelの特定のキーを持つ要素を抽出する関数を連想させますが、本定数は子要素が「配列型」であるかを判別して再帰処理を限定する点が異なります。この定数は、設定ファイルやデータ構造の中で、特定のリストやグループなど、ネストされた「配列の構造」だけを効率的に探索・処理したい場合に特に有用です。
この定数は、多次元配列を走査する際、子要素が「配列」である場合にのみ再帰的に深掘りすることを制御します。Laravelのarray_onlyヘルパー関数のように特定のキーを抽出する機能とは異なり、走査する要素の種類に着目する点にご注意ください。CHILD_ARRAYS_ONLYを指定しないデフォルトの挙動とは異なり、スカラー値やオブジェクトの内部には再帰的に深入りしません。そのため、配列としての構造だけを効率的に探索したい場合に特に有用ですが、オブジェクトのプロパティなどもすべて走査したい場合はこの定数を使用しないでください。目的によって使い分けが重要です。