extract(array $array, int $flags = EXTR_OVERWRITE, string $prefix = ''): int
返回成功導入的變量數量。僅對關聯數組有效,數字索引被忽略。
| 常量 | 衝突時行為 | 典型用途 |
|---|---|---|
EXTR_OVERWRITE | 覆蓋現有同名變量(默認) | 模板引擎渲染上下文 |
EXTR_SKIP | 跳過,保留現有變量 | 合併配置,優先級:現有 > 新數組 |
EXTR_PREFIX_SAME | 衝突時加前綴 {$prefix}_{$key} | 安全導入用戶輸入,避免污染 |
EXTR_PREFIX_ALL | 所有導入變量加前綴 {$prefix}_{$key} | 命名空間隔離,如 form_name |
EXTR_PREFIX_INVALID | 非法變量名(如數字開頭)加前綴 | 處理非標準鍵名數據源 |
EXTR_IF_EXISTS | 僅覆蓋已存在的變量 | 從數組更新已聲明變量 |
EXTR_PREFIX_IF_EXISTS | 僅對已存在變量加前綴導入 | 罕用 |
EXTR_REFS | 以引用導入(修改變量影響原數組) | 需雙向同步場景 |
<?php
$size = 'old size';
$data = ['color' => 'red', 'size' => 'XXL', 'price' => '53'];
extract($data); // EXTR_OVERWRITE
echo "color=$color, size=$size, price=$price\n";
// 輸出:color=red, size=XXL, price=53 ($size 被覆蓋)
<?php
$data = ['color' => 'red', 'size' => 'XXL', 'price' => '53'];
// 所有變量加 form_ 前綴
extract($data, EXTR_PREFIX_ALL, 'form');
// 產生:$form_color, $form_size, $form_price
echo $form_color; // red
// 原 $color 等不受影響
<?php
$data = ['color' => 'red'];
extract($data, EXTR_REFS);
$color = 'green';
echo $data['color']; // green (原數組被修改)
$data['color'] = 'blue';
echo $color; // blue (變量同步更新)
<?php
function renderTemplate($templateFile, array $context) {
// 1. 預定義安全變量(防止模板覆蓋關鍵變量)
$safeVars = ['escape' => 'htmlspecialchars', 'url' => 'urlencode'];
// 2. 僅導入白名單上下文,加前綴隔離
$allowed = array_intersect_key($context, array_flip(['title', 'content', 'user']));
extract($allowed, EXTR_PREFIX_ALL, 'tpl');
// 3. 包含模板(模板中使用 $tpl_title, $tpl_content...)
ob_start();
include $templateFile;
return ob_get_clean();
}
// 模板文件 template.php
// <h1><?= htmlspecialchars($tpl_title) ?></h1>
// <div><?= $tpl_content ?></div>
extract($_POST) 或 extract($_GET) 允許攻擊者覆蓋任意變量(如 $isAdmin = true)。嚴禁直接提取超全局數組。extract() 導入的變量留在局部作用域,但 EXTR_REFS 可能修改外部引用數組。array_merge($defaults, $userConfig) 或 $config = new Config($file); $config->merge($arr);class UserData { public function __construct(array $data) { ... } }$key => $value:$key 是否合法變量名(正則 ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$)$flags 決定目標變量名(加前綴/跳過/覆蓋)EG(active_symbol_table) 中創建/更新條目EXTR_REFS 時設置 is_ref=1 指向同一 zvalextract() 是把雙刃劍:在受控上下文(模板渲染、配置合併)配合 EXTR_PREFIX_ALL 極其便利;但在處理不可信輸入時是安全噩夢。現代 PHP 開發應優先選擇顯式數據傳遞(DTO、模板引擎上下文),僅在極簡腳本或歷史代碼維護中謹慎使用。