extract — 連想配列のキーを変数に展開する

PHP
  • カテゴリ: PHP
  • 掲載バージョン: PHP 8.4
  • 名前空間 / FQCN / コマンド: extract(グローバル関数)
  • 関連: compact / parse_str / array_merge / get_defined_vars / list
  • 変更履歴: なし(PHP7以降は配列以外で TypeError

要点(TL;DR)

  • 連想配列のキーを、そのまま変数として現在のスコープへ取り込む
  • 最低限の使い方:extract($data, EXTR_SKIP);
  • よくある罠
    • 既存変数の上書き(既定は EXTR_OVERWRITE
    • 外部入力$_GET 等)に対して使うと予期せぬ変数注入
    • EXTR_REFS による参照の副作用

概要

extract() は連想配列のキーを変数名、値を変数値として現在のシンボルテーブルに取り込みます。テンプレート表示や設定配列の展開に便利ですが、既存変数の上書きや外部入力の混入に注意が必要です。実務ではフラグ指定とプレフィックスで衝突を避けるのが定石です。

構文 / シグネチャ

int extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = "");
  • 引数(表)
引数必須既定値説明
arrayarray(参照渡し)展開する連想配列。EXTR_REFS 時は参照が張られる
flagsintEXTR_OVERWRITE取り込みルール(下記)
prefixstring""プレフィックス(EXTR_PREFIX_* 指定時に使用)

主なフラグ

  • EXTR_OVERWRITE(既定): 既存変数を上書き
  • EXTR_SKIP: 既存変数は保持(新規のみ作成)
  • EXTR_IF_EXISTS: 既にある変数だけ上書き(新規は作らない)
  • EXTR_PREFIX_SAME / EXTR_PREFIX_ALL / EXTR_PREFIX_INVALID / EXTR_PREFIX_IF_EXISTS: 衝突・無効名時などに "$prefix_{$key}" で作成
  • EXTR_REFS: 参照として取り込み(変数と配列の値が連動)
  • 戻り値:作成・更新された変数の個数(int)
  • 例外/副作用
    • TypeError:第1引数が配列でない
    • E_WARNING:無効なプレフィックスなど
    • EXTR_REFS:配列要素と展開先変数が参照で結び付く(相互に影響)

使用例

最小例

<?php
// 最小・安全寄り(既存変数を守る)
$data = ['name' => 'Alice', 'age' => 20];

$age = 99;                     // 既存
$count = extract($data, EXTR_SKIP);

echo $name;  // Alice
echo $age;   // 99(上書きされない)
echo $count; // 2(展開できた数)

実務例

<?php
// 1) 設定配列をプレフィックス付きで展開(衝突回避)
$cfg = ['name' => 'myapp', 'debug' => true, 'timezone' => 'Asia/Tokyo'];
extract($cfg, EXTR_PREFIX_ALL, 'app'); // $app_name, $app_debug, $app_timezone

// 2) DB行を「既存変数のみ」上書き(意図しない新規変数を作らない)
$pdo = new PDO('sqlite::memory:');
$pdo->exec("CREATE TABLE posts(id INTEGER, title TEXT)");
$pdo->exec("INSERT INTO posts VALUES(1, 'Hello')");

$row = $pdo->query("SELECT id, title FROM posts LIMIT 1")->fetch(PDO::FETCH_ASSOC);
$id = null; $title = '';        // 期待する変数だけ事前定義
extract($row, EXTR_IF_EXISTS);  // $id と $title のみ上書き

// 3) 参照で展開(更新が元配列へ反映)
$state = ['count' => 1];
extract($state, EXTR_REFS); // $count は $state['count'] への参照
$count++;
assert($state['count'] === 2);

よくある落とし穴・注意

  • 既定の EXTR_OVERWRITE破壊的(既存変数を上書き)。実務は EXTR_SKIP / EXTR_IF_EXISTS が無難。
  • 外部入力($_GET/$_POST 等)には使わない。安全に扱うなら明示的に代入・バリデーション。
  • 無効なキー(数値開始・空白/記号)は変数化されない。EXTR_PREFIX_INVALIDEXTR_PREFIX_ALL を使っても、名前として無効ならスキップされ得る。
  • EXTR_REFS副作用大。テストや読みやすさの観点で慎重に。
  • 計算量は O(n)。巨大配列で乱用するより、必要なキーのみ取り出す方が明瞭で高速。

代替・関連APIとの比較

  • 手動代入($x = $arr['x'] ?? ...;:冗長だが安全・明示的。外部入力や重要コードで推奨。
  • 配列分割(構造的代入)['x' => $x, 'y' => $y] = $arr;(キーが確定している時に型安全・読みやすい
  • compact():逆方向(変数 → 連想配列)。テンプレート/返却値の構築に。
  • array_merge():配列同士の結合。変数展開は不要な場面でこちらが適切。

テスト例(Pest)

<?php

it('skips overwrite and counts imported vars', function () {
    $data = ['a' => 1, 'b' => 2];
    $a = 9;
    $n = extract($data, EXTR_SKIP);
    expect($n)->toBe(2)
        ->and($a)->toBe(9)
        ->and($b)->toBe(2);
});

it('links by reference with EXTR_REFS', function () {
    $state = ['count' => 1];
    extract($state, EXTR_REFS);
    $count++;
    expect($state['count'])->toBe(2);
});

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

症状/エラー原因対処
TypeError: extract(): Argument #1 ($array) must be of type array配列以外を渡している事前に is_array で確認、または適切な変換
extract(): prefix is not a valid identifierプレフィックスが無効(数字開始・記号等)英字 or _ で開始する有効な識別子に修正
変数が思わぬ値に置き換わる既定 EXTR_OVERWRITE による上書きEXTR_SKIP / EXTR_IF_EXISTS / EXTR_PREFIX_* を使用
期待する変数が作成されないキーが存在しない/無効、または EXTR_IF_EXISTS のため新規作成されないキーを確認、必要なら事前に変数を定義またはフラグ見直し
値の更新が元配列に波及するEXTR_REFS による参照取り込み参照を避けたい場合は EXTR_REFS を外す、または配列をコピー

PHPカテゴリの補足

  • 必要拡張:なし(標準)
  • エラー形態TypeError(非配列)、E_WARNING(無効プレフィックスなど)
  • エンコーディング注意:変数名は英数字とアンダースコアのみ。多バイト文字キーはそのままでは変数化できない場合がある
  • 8.1/8.2/8.3/8.4差分:実用上の仕様差分はほぼなし(型厳格化は7系から)

参考リンク

長野県・北アルプス地方在住のフリーランスWebプログラマー。
「落ち着くためのWeb開発」をテーマに、訪れる人が安心して使えるサービスづくりを心がけています。

LaravelやWordPressなどのWebアプリケーション開発を得意とし、技術面の安定性はもちろん、運用後も長く活用できる設計を大切にしています。
静かな山間の暮らしから生まれる視点で、シンプルかつ本質的な解決策をご提案します。

野鳥観察も趣味のひとつで、特にミソサザイ(Wren)に魅力を感じています。
小さな体に反して力強く上向きの尾羽、そして澄んだ鳴き声が遠くまで響く姿に、静かな存在感と芯の強さを感じます。
このサイト名「Laravel Wren」には、そんなミソサザイのように、小さくても確かな価値を届けたいという想いを込めています。

信頼できるパートナーとして、そして気軽に相談できる存在として、あなたのWebプロジェクトをサポートします。

Yudai Tsuyuzakiをフォローする