list() 是PHP的語言構造(非函數),用於將數值索引陣列的值一次性賦值給多個變數。類似於現代語言的「解構賦值」,是處理固定結構陣列(如資料庫查詢結果、CSV行、爆炸字串)的利器。
list($var1, $var2, $var3) = $array;
// 等同於
$var1 = $array[0];
$var2 = $array[1];
$var3 = $array[2];
| 限制 | 說明 | 範例 |
|---|---|---|
| 僅支援數值索引 | 關聯陣列(string key)無效 | list($a, $b) = ['x'=>1, 'y'=>2]; // $a=null, $b=null |
| 索引必須從0開始連續 | 缺失索引會導致對應變數為null | list($a, $b) = [1=>'a', 2=>'b']; // $a=null |
| 賦值順序:從右至左 | 影響引用賦值與副作用操作 | 見下文「陷阱」章節 |
| PHP 7.1+ 支援指定鍵名 | list('key' => $var) = $arr | 下文有詳細範例 |
<?php
$info = ['coffee', 'brown', 'caffeine'];
// 一次賦值三個變數
list($drink, $color, $power) = $info;
echo "$drink is $color and $power makes it special.\n";
// 輸出: coffee is brown and caffeine makes it special.
<?php
$info = ['coffee', 'brown', 'caffeine'];
// 只取第一、三個值(中間留空)
list($drink, , $power) = $info;
echo "$drink has $power.\n";
// 輸出: coffee has caffeine.
// 只取第三個值
list(, , $power) = $info;
echo "I need $power!\n";
// 輸出: I need caffeine!
<?php
// 假設 $conn 為有效 mysqli 連線
$result = $conn->query("SELECT id, name, salary FROM employees");
echo "<table><tr><th>員工</th><th>薪資</th></tr>";
while (list($id, $name, $salary) = $result->fetch_row()) {
echo "<tr>";
echo "<td><a href='info.php?id=$id'>" . htmlspecialchars($name) . "</a></td>";
echo "<td>" . number_format($salary) . "</td>";
echo "</tr>";
}
echo "</table>";
$result->free();
?>
<?php
$csvLine = '2024-01-15,張三,工程師,80000,Taipei';
// 直接爆炸並解構
list($date, $name, $title, $salary, $city) = explode(',', $csvLine);
echo "姓名: $name, 職稱: $title, 薪資: $salary, 城市: $city";
// 輸出: 姓名: 張三, 職稱: 工程師, 薪資: 80000, 城市: Taipei
<?php
// 僅 PHP 7.1+
$user = [
'id' => 1001,
'name' => '李四',
'email' => 'lisi@example.com',
'role' => 'admin'
];
// 指定鍵名提取,順序無關,支援關聯陣列!
list('name' => $name, 'email' => $email) = $user;
echo "Name: $name, Email: $email\n";
// 輸出: Name: 李四, Email: lisi@example.com
// 同時使用短陣列語法 []
['id' => $id, 'role' => $role] = $user;
echo "ID: $id, Role: $role";
// 輸出: ID: 1001, Role: admin
<?php
$data = [
['id' => 1, 'meta' => ['created' => '2024-01-01', 'ip' => '192.168.1.1']],
['id' => 2, 'meta' => ['created' => '2024-01-02', 'ip' => '10.0.0.1']]
];
foreach ($data as ['id' => $id, 'meta' => ['created' => $created, 'ip' => $ip]]) {
echo "ID: $id, Created: $created, IP: $ip\n";
}
官方文檔明確警告:list() 從最右邊參數開始賦值。對簡單變數無影響,但陣列索引賦值會產生反直覺結果:
<?php
$info = ['coffee', 'brown', 'caffeine'];
// ❌ 錯誤預期:$a[0]='coffee', $a[1]='brown', $a[2]='caffeine'
list($a[0], $a[1], $a[2]) = $info;
// ✅ 實際結果(從右至左賦值):
// 1. $a[2] = 'caffeine'
// 2. $a[1] = 'brown'
// 3. $a[0] = 'coffee'
// 但 $a 陣列在賦值過程中被重建,最終順序顛倒!
var_dump($a);
/*
array(3) {
[2]=> string(8) "caffeine"
[1]=> string(5) "brown"
[0]=> string(6) "coffee"
}
*/
<?php
// 方法 1:array_merge 保證順序
$a = array_merge([], $info); // [0=>'coffee', 1=>'brown', 2=>'caffeine']
// 方法 2:foreach 重建
$a = [];
foreach ($info as $k => $v) {
$a[$k] = $v;
}
// 方法 3:PHP 7.1+ 指定鍵名(推薦)
[0 => $a[0], 1 => $a[1], 2 => $a[2]] = $info;
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| list() | 語法簡潔、無函數呼叫開銷、支援跳過值 | 僅數值索引、賦值順序陷阱、無預設值機制 | 固定結構數值陣列、資料庫fetch_row、explode結果 |
陣列解構 [$a, $b] = $arr | 短語法、PHP 7.1+支援鍵名、行為一致 | 需PHP 7.1+ | 現代代碼庫、關聯陣列解構 |
| extract() | 關聯陣列轉變數、支援前綴 | 安全風險、變數污染、難除錯 | 模板引擎變數注入(謹慎使用) |
| foreach + list | 迭代多維陣列解構 | 語法較繁瑣 | 多行資料處理 |
<?php
$arr = range(1, 1000000);
$iterations = 100;
// list()
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
list($a, $b, $c) = $arr;
}
echo "list(): " . (microtime(true) - $start) . "s\n";
// 短陣列語法
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
[$a, $b, $c] = $arr;
}
echo "[] syntax: " . (microtime(true) - $start) . "s\n";
// 直接索引
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$a = $arr[0]; $b = $arr[1]; $c = $arr[2];
}
echo "direct index: " . (microtime(true) - $start) . "s\n";
/*
典型輸出:
list(): 0.12s
[] syntax: 0.11s
direct index: 0.08s
差異微小,優先考慮可讀性
*/
fetch_row()、explode()、fgetcsv() 等場景[] 更強大:支援關聯陣列鍵名指定、巢狀解構、行為更直觀[] 語法,舊版本維護時使用 list()