在PHP 中, array_fill()是一個非常方便的函數,用於用指定的值填充數組。它通常用於初始化數組,特別是在我們需要快速生成一個默認值數組時。然而,很多開發者在使用array_fill()創建二維數組時,容易陷入一些常見的誤區,導致程序出現意想不到的行為。本文將探討這些常見錯誤以及如何正確地避免它們。
在深入問題之前,先簡單回顧一下array_fill()的基本用法:
$filledArray = array_fill(0, 5, 'default');
// 結果: ['default', 'default', 'default', 'default', 'default']
這個函數接受三個參數:
起始索引(從哪個索引開始填充)
數組長度(填充幾個元素)
填充值
當我們試圖使用array_fill()來創建一個二維數組,比如5 行,每行3 個默認值'default' ,許多開發者會寫出如下代碼:
$matrix = array_fill(0, 5, array_fill(0, 3, 'default'));
乍一看,這樣的寫法似乎是合理的。輸出結果也如預期:
[
['default', 'default', 'default'],
['default', 'default', 'default'],
['default', 'default', 'default'],
['default', 'default', 'default'],
['default', 'default', 'default']
]
但問題在於:這些子數組其實是同一個數組的引用!
也就是說,如果我們修改其中一個子數組的值:
$matrix[0][0] = 'changed';
會導致所有行的第一個值都變成'changed' :
[
['changed', 'default', 'default'],
['changed', 'default', 'default'],
['changed', 'default', 'default'],
['changed', 'default', 'default'],
['changed', 'default', 'default']
]
這是由於array_fill()在第三個參數是數組時,填充的是同一個數組的引用,而不是每次創建一個新的數組實例。
為了解決這個問題,我們需要確保每個子數組都是獨立的實例。最穩妥的做法是使用循環:
$matrix = [];
for ($i = 0; $i < 5; $i++) {
$matrix[$i] = array_fill(0, 3, 'default');
}
這樣就能保證每一行的數組都是新的副本,相互之間不會相互影響。
如果你封裝了一個創建二維數組的函數,也要注意不要在函數外部創建子數組然後復用。例如:
錯誤示範:
function createMatrix($rows, $cols, $defaultValue) {
$rowTemplate = array_fill(0, $cols, $defaultValue);
return array_fill(0, $rows, $rowTemplate);
}
這個問題和上面描述的一樣,所有行都引用了同一個$rowTemplate 。修改一行,會影響所有行。
正確寫法:
function createMatrix($rows, $cols, $defaultValue) {
$matrix = [];
for ($i = 0; $i < $rows; $i++) {
$matrix[] = array_fill(0, $cols, $defaultValue);
}
return $matrix;
}
假設你在構建一個在線填空題生成工具(比如https://m66.net/tools/quiz-generator ),需要創建一個空白題板,其中每格默認值為null :
$questionBoard = [];
for ($i = 0; $i < 10; $i++) {
$questionBoard[] = array_fill(0, 5, null);
}
這樣的做法可以避免將整個題板意外共享內存,從而在用戶交互或後續邏輯中引發Bug。
array_fill()是一個高效的工具,但當涉及到嵌套數組(二維或多維)時,我們必須警惕共享引用的問題。通過使用循環並確保每個子數組是一個新的實例,我們就能構建更加健壯和可預測的數據結構。
理解PHP 中的值與引用機制,不僅有助於避免這個問題,也能提升你在大型項目中處理複雜數組結構的能力。