Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】EXTR_REFS定数の使い方

EXTR_REFS定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

EXTR_REFS定数は、PHPのextract()関数と組み合わせて使用される定数で、配列から変数への値のインポート方法を制御します。PHPのextract()関数は、連想配列のキーを変数名とし、そのキーに対応する値を新しい変数として作成する機能を提供します。通常、この関数は配列の値をコピーして変数を作成するため、作成された変数を変更しても元の配列の値には影響がありません。

しかし、extract()関数の第二引数であるextract_typeEXTR_REFS定数を指定した場合、この挙動が特別になります。EXTR_REFSを使用すると、配列から展開される変数は、元の配列の対応する要素への「参照」として作成されます。これは、新しい変数が元の配列の要素と同じメモリ上の値を指し示すことを意味します。そのため、作成された変数の値を変更すると、同時に元の配列のその要素の値も変更されることになります。

この定数は、配列のデータを動的に多数の変数として扱いながら、それらの変数を通じて元の配列のデータを直接操作したい場合に非常に便利です。ただし、参照による変数の変更は元の配列にも影響を及ぼすため、予期せぬデータの変更を防ぐためにも、その挙動を十分に理解した上で利用することが重要です。主に、既存の配列の内容をその場で更新するようなシナリオで活用されます。

構文(syntax)

1<?php
2$myArray = ['key1' => 'value1', 'key2' => 'value2'];
3extract($myArray, EXTR_REFS);
4?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP extract() と EXTR_REFS で参照を操作する

1<?php
2
3/**
4 * EXTR_REFS 定数の動作をデモンストレーションする関数
5 *
6 * EXTR_REFS は extract() 関数で使用されるフラグです。
7 * このフラグを指定すると、配列の値を現在のシンボルテーブルに変数としてインポートする際に、
8 * 元の配列の要素への「参照」としてインポートします。
9 * そのため、インポートされた変数の値を変更すると、元の配列の要素も変更されます。
10 * これに対し、EXTR_REFS を使用しない場合(デフォルトの動作など)は、値がコピーとしてインポートされるため、
11 * 変数の変更は元の配列には影響しません。
12 */
13function demonstrateExtractRefs(): void
14{
15    echo "--- extract() と EXTR_REFS の動作比較 ---" . PHP_EOL . PHP_EOL;
16
17    // 1. サンプルとなる連想配列を準備
18    $userProfile = [
19        'name' => 'Alice',
20        'age' => 30,
21        'city' => 'New York',
22    ];
23
24    echo "■ 元の配列の状態:" . PHP_EOL;
25    print_r($userProfile);
26    echo PHP_EOL;
27
28    // --- A. EXTR_REFS を使用しない場合 (値のコピー) ---
29    echo "--- A. EXTR_REFS を使用しない場合 (値のコピー) ---" . PHP_EOL;
30    // 比較のために元の配列をコピーして使用
31    $dataCopy = $userProfile;
32
33    // extract() を実行 (デフォルトでは EXTR_OVERWRITE のように動作することが多い)
34    // ここで $name, $age, $city 変数が作成され、それぞれ $dataCopy の値がコピーされます。
35    extract($dataCopy);
36
37    echo "1. extract() 後の変数 (\$name, \$age, \$city):" . PHP_EOL;
38    echo "   \$name: {$name}" . PHP_EOL;
39    echo "   \$age: {$age}" . PHP_EOL;
40    echo "   \$city: {$city}" . PHP_EOL . PHP_EOL;
41
42    // インポートされた変数の値を変更
43    $name = 'Bob';
44    $age = 35;
45    echo "2. インポートされた変数を変更後 (\$name = 'Bob', \$age = 35):" . PHP_EOL;
46    echo "   \$name: {$name}" . PHP_EOL;
47    echo "   \$age: {$age}" . PHP_EOL . PHP_EOL;
48
49    // 元の配列 ($dataCopy) がどうなったか確認
50    echo "3. 元の配列 (\$dataCopy) の状態:" . PHP_EOL;
51    print_r($dataCopy);
52    echo "   -> 元の配列は変更されていません。変数は値のコピーだったため。" . PHP_EOL . PHP_EOL;
53
54    // --- B. EXTR_REFS を使用する場合 (値の参照) ---
55    echo "--- B. EXTR_REFS を使用する場合 (値の参照) ---" . PHP_EOL;
56    // 比較のために元の配列を再度コピーして使用
57    $dataRefs = $userProfile;
58
59    // EXTR_REFS フラグを指定して extract() を実行
60    // ここで $name, $age, $city 変数が作成され、それぞれ $dataRefs の要素への「参照」となります。
61    extract($dataRefs, EXTR_REFS);
62
63    echo "1. extract(..., EXTR_REFS) 後の変数 (\$name, \$age, \$city):" . PHP_EOL;
64    echo "   \$name: {$name}" . PHP_EOL;
65    echo "   \$age: {$age}" . PHP_EOL;
66    echo "   \$city: {$city}" . PHP_EOL . PHP_EOL;
67
68    // インポートされた変数の値を変更
69    $name = 'Charlie';
70    $age = 40;
71    $city = 'London';
72    echo "2. インポートされた変数を変更後 (\$name = 'Charlie', \$age = 40, \$city = 'London'):" . PHP_EOL;
73    echo "   \$name: {$name}" . PHP_EOL;
74    echo "   \$age: {$age}" . PHP_EOL;
75    echo "   \$city: {$city}" . PHP_EOL . PHP_EOL;
76
77    // 元の配列 ($dataRefs) がどうなったか確認
78    echo "3. 元の配列 (\$dataRefs) の状態:" . PHP_EOL;
79    print_r($dataRefs);
80    echo "   -> 元の配列が変更されています。変数は元の配列の要素への参照だったため。" . PHP_EOL . PHP_EOL;
81}
82
83// 関数を実行してデモンストレーションを表示
84demonstrateExtractRefs();
85

PHPのEXTR_REFSは、extract()関数と組み合わせて使用する定数です。この定数をextract()関数の第二引数に指定することで、配列から変数を作成する際の挙動を制御します。

EXTR_REFSが指定されると、配列のキーを変数名とし、対応する値を新しい変数としてインポートする際に、元の配列の要素への「参照」として変数を扱います。これにより、新しく生成された変数の値を変更すると、参照元の配列にある該当する要素の値も自動的に更新されます。これは、変数が元の配列の要素を直接指し示す状態にあるためです。

一方、EXTR_REFSを指定しないextract()関数のデフォルトの動作では、配列の要素が単純な「コピー」として変数にインポートされます。この場合、変数の値を変更しても、元の配列には一切影響を与えません。

提供されたサンプルコードは、この「参照」と「コピー」の違いを明確に比較して示しています。コードでは、まずEXTR_REFSなしでextract()を実行し、変数を変更しても元の配列は変わらないことを確認します。その後、EXTR_REFSを指定して再度extract()を実行し、同じように変数を変更すると、元の配列も更新される様子をデモンストレーションしています。EXTR_REFS定数自体には引数や戻り値はありませんが、extract()関数の重要なオプションとして、変数と配列の関係性を制御する役割を持っています。

EXTR_REFS定数をextract()関数で使用すると、配列から生成された変数は元の配列の要素への「参照」として扱われます。そのため、生成された変数の値を変更すると、元の配列のデータも直接変更されてしまいます。これは意図しないデータ破壊や予期せぬ動作につながる可能性があるため、この定数を使う際は、変数の変更が元の配列に与える影響を十分に理解し、慎重に利用してください。

また、extract()関数自体が、既存の変数名と配列のキーが衝突するリスクを伴い、予期せぬ変数の上書きやセキュリティ上の問題を引き起こす可能性がある点にも注意が必要です。利用する際は、その挙動を完全に把握している場合に限定し、必要な範囲で安全に使うことをお勧めします。特に、ユーザー入力など信頼できないデータには安易に適用しないでください。

EXTR_REFSで配列をリファレンス抽出する

1<?php
2
3/**
4 * Demonstrates the usage of the EXTR_REFS constant with the extract() function.
5 *
6 * EXTR_REFS extracts variables from an array into the current symbol table
7 * as references. This means that changes to the extracted variables will
8 * directly affect the original array's values, and vice-versa.
9 * Understanding how PHP handles references is fundamental when working with
10 * variable scopes, which can be important in advanced topics such as
11 * developing PHP extensions (e.g., using php ext_skel to scaffold).
12 */
13function demonstrateExtractWithRefs(): void
14{
15    // Initialize an associative array
16    $originalData = [
17        'product' => 'Laptop',
18        'price' => 1200,
19    ];
20
21    echo "Initial \$originalData array:\n";
22    print_r($originalData);
23
24    // Use extract() with EXTR_REFS to extract variables by reference.
25    // The keys 'product' and 'price' from $originalData become new
26    // variables $product and $price in the current scope, referencing
27    // the values in $originalData.
28    extract($originalData, EXTR_REFS);
29
30    echo "\nAfter extract(\$originalData, EXTR_REFS):\n";
31    echo "Extracted variable \$product: " . $product . "\n";
32    echo "Extracted variable \$price: " . $price . "\n";
33
34    // Modify an extracted variable.
35    // Because EXTR_REFS was used, this modification will also change
36    // the corresponding value in the $originalData array.
37    $product = 'Desktop PC';
38    echo "\nAfter modifying \$product to 'Desktop PC' (via extracted variable):\n";
39    echo "Extracted variable \$product: " . $product . "\n";
40
41    // Observe the change in the original array.
42    // The 'product' key in $originalData should now reflect the change.
43    echo "Final \$originalData array after modifications through reference:\n";
44    print_r($originalData);
45
46    // Verification: Confirm that the original array's value was indeed updated.
47    if ($originalData['product'] === 'Desktop PC') {
48        echo "Verification: The original array's 'product' value was updated via the extracted reference.\n";
49    } else {
50        echo "Verification: Something went wrong with the reference.\n";
51    }
52}
53
54// Execute the demonstration function
55demonstrateExtractWithRefs();

PHPのEXTR_REFSは、PHP 8で利用できる定数の一つです。主に、配列のキーを変数として現在のスコープに展開するextract()関数と組み合わせて使用されます。

この定数をextract()関数の第二引数に指定すると、配列から抽出される各変数が、元の配列の対応する値への「参照」として作成されます。具体的には、新しく生成された変数(例:配列の'product'キーから$product変数)を変更すると、元の配列の'product'キーの値も自動的に更新されます。これは、変数が値をコピーするのではなく、元のデータの場所を指し示しているためです。

このように参照として変数を扱うことで、元の配列のデータを効率的に操作したり、複数の場所から同じデータを共有・変更したりする際に非常に便利です。変数と元のデータとの強い連動性を理解することは、PHPのスコープ管理や、php ext_skelのようなツールを使ってPHPの拡張機能を開発する際の基礎知識としても役立ちます。この定数には引数はなく、特定の戻り値もありません。

EXTR_REFS定数を用いてextract()関数で配列から変数を抽出する際、それらの変数は元の配列の要素と「参照」として紐付けられます。このため、抽出した変数の値を変更すると、元の配列の値も同時に変わる点に特に注意が必要です。意図しないデータ変更や、既存の変数名を上書きしてしまう可能性があるため、コードの可読性や保守性を考慮する際には、その影響を十分に理解して利用することが重要です。予期せぬ副作用を防ぐため、安易な使用は避け、変数のスコープとライフサイクルを慎重に管理してください。

関連コンテンツ

関連プログラミング言語