通過(guò)參數列表可以傳遞信息到函數,即以逗號作為分隔符的表達式列表。函數在實(shí)際調用之前,值參數是從左向右求值的(及早求值)。
PHP 支持按值傳遞參數(默認),通過(guò)引用傳遞參數 以及 默認參數。也支持 可變長(cháng)度參數列表 和 命名參數。
示例 #1 向函數傳遞數組
<?php
function takes_array($input)
{
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
?>
從 PHP 8.0.0 開(kāi)始,函數參數列表可以包含一個(gè)尾部的逗號,這個(gè)逗號將被忽略。這在參數列表較長(cháng)或包含較長(cháng)的變量名的情況下特別有用,這樣可以方便地垂直列出參數。
示例 #2 函數參數使用尾部逗號
<?php
function takes_many_args(
$first_arg,
$second_arg,
$a_very_long_argument_name,
$arg_with_default = 5,
$again = 'a default string', // 在 8.0.0 之前,這個(gè)尾部的逗號是不允許的。
)
{
// ...
}
?>
從 PHP 8.0.0 開(kāi)始,廢棄在可選參數后聲明強制參數??梢酝ㄟ^(guò)刪除默認值來(lái)解決。
此規則一個(gè)例外是 Type $param = null
形式的參數,
其中 null
默認值使類(lèi)型隱性允許為空。
這種做法依然允許,但是推薦使用顯性可為 null 的類(lèi)型代替。
示例 #3 強制參數后聲明可選參數
<?php
function foo($a = [], $b) {} // 之前
function foo($a, $b) {} // 之后
function bar(A $a = null, $b) {} // 同時(shí)可用
function bar(?A $a, $b) {} // 官方推薦的寫(xiě)法
?>
默認情況下,函數參數通過(guò)值傳遞(因而即使在函數內部改變參數的值,它并不會(huì )改變函數外部的值)。如果希望允許函數修改它的參數值,必須通過(guò)引用傳遞參數。
如果想要函數的一個(gè)參數總是通過(guò)引用傳遞,可以在函數定義中該參數的前面加上符號 &:
示例 #4 用引用傳遞函數參數
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // 輸出 'This is a string, and something extra.'
?>
函數可以定義 C++ 風(fēng)格的標量參數默認值,如下所示:
示例 #5 在函數中使用默認參數
<?php
function makecoffee($type = "cappuccino")
{
return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>
以上例程會(huì )輸出:
Making a cup of cappuccino. Making a cup of . Making a cup of espresso.
PHP 還允許使用數組 array 和特殊類(lèi)型 null
作為默認參數,例如:
示例 #6 使用非標量類(lèi)型作為默認參數
<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
return "Making a cup of ".join(", ", $types)." with $device.\n";
}
echo makecoffee();
echo makecoffee(array("cappuccino", "lavazza"), "teapot");
?>
默認值必須是常量表達式,不能是諸如變量,類(lèi)成員,或者函數調用等。
注意當使用默認參數時(shí),任何默認參數必須放在任何非默認參數的右側;否則,函數將不會(huì )按照預期的情況工作??紤]下面的代碼片斷:
示例 #7 函數默認參數的不正確用法
<?php
function makeyogurt($type = "acidophilus", $flavour)
{
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt("raspberry"); // 不會(huì )按照預期工作
?>
以上例程會(huì )輸出:
Warning: Missing argument 2 in call to makeyogurt() in /usr/local/etc/httpd/htdocs/phptest/functest.html on line 41 Making a bowl of raspberry .
現在,比較上面的例子和這個(gè)例子:
示例 #8 函數默認參數正確的用法
<?php
function makeyogurt($flavour, $type = "acidophilus")
{
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt("raspberry"); // 按預期工作
?>
以上例程會(huì )輸出:
Making a bowl of acidophilus raspberry.
注意: 傳引用的參數也可以有默認值。
PHP 在用戶(hù)自定義函數中支持可變數量的參數列表。由
...
語(yǔ)法實(shí)現。
注意: 還可以使用以下函數來(lái)獲取可變參數 func_num_args()、 func_get_arg() 和 func_get_args(),不建議使用此方式,請使用
...
來(lái)替代。
包含 ...
的參數,會(huì )轉換為指定參數變量的一個(gè)數組,見(jiàn)以下示例:
示例 #9 使用 ...
來(lái)訪(fǎng)問(wèn)變量參數
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
以上例程會(huì )輸出:
10
也可以使用 ...
語(yǔ)法來(lái)傳遞 array 或
Traversable
做為參數到函數中:
示例 #10 使用 ...
來(lái)傳遞參數
<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>
以上例程會(huì )輸出:
3 3
你可以在
...
前指定正常的位置參數。在這種情況下,只有不符合位置參數的尾部參數才會(huì )被添加到
...
生成的數組中。
你也可以在
...
標記前添加一個(gè)
類(lèi)型聲明。如果存在這種情況,那么
...
捕獲的所有參數都必須匹配參數類(lèi)型。
示例 #11 輸入提示的變量參數
<?php
function total_intervals($unit, DateInterval ...$intervals) {
$time = 0;
foreach ($intervals as $interval) {
$time += $interval->$unit;
}
return $time;
}
$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' days';
// 這將會(huì )失敗,因為 null 不是 DateInterval 對象。
echo total_intervals('d', null);
?>
以上例程會(huì )輸出:
3 days Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
最后,你還可以給參數傳遞
引用變量,通過(guò)在
...
前加上一個(gè) (&
) 符號來(lái)實(shí)現。
不需要特殊的語(yǔ)法來(lái)聲明一個(gè)函數是可變的;但是訪(fǎng)問(wèn)函數的參數必須使用 func_num_args(), func_get_arg() 和 func_get_args() 函數。
上面的第一個(gè)例子在早期 PHP 版本中的實(shí)現如下:
示例 #12 在 PHP 早期版本中訪(fǎng)問(wèn)可變參數
<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
以上例程會(huì )輸出:
10
PHP 8.0.0 開(kāi)始引入了命名參數作為現有位置參數的擴展。命名參數允許根據參數名而不是參數位置向函數傳參。這使得參數的含義自成體系,參數與順序無(wú)關(guān),并允許任意跳過(guò)默認值。
命名參數通過(guò)在參數名前加上冒號來(lái)傳遞。允許使用保留關(guān)鍵字作為參數名。參數名必須是一個(gè)標識符,不允許動(dòng)態(tài)指定。
示例 #13 命名參數的語(yǔ)法
<?php
myFunction(paramName: $value);
array_foobar(array: $value);
// 不支持。
function_name($variableStoringParamName: $value);
?>
示例 #14 通過(guò)位置傳參與命名參數的對比
<?php
// 使用順序傳遞參數:
array_fill(0, 100, 50);
// 使用命名參數:
array_fill(start_index: 0, count: 100, value: 50);
?>
指定參數的傳遞順序并不重要。
示例 #15 參數順序不同的示例(同上例)
<?php
array_fill(value: 50, count: 100, start_index: 0);
?>
命名參數也可以與位置參數相結合使用。此種情況下,命名參數必須在位置參數之后。也可以只指定一個(gè)函數的部分可選參數,而不考慮它們的順序。
示例 #16 命名參數與位置參數結合使用
<?php
htmlspecialchars($string, double_encode: false);
// 等價(jià)于
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>
Passing the same parameter multiple times results in an Error exception.
示例 #17 Error exception when passing the same parameter multiple times
<?php
function foo($param) { ... }
foo(param: 1, param: 2);
// 錯誤:命名參數 $param 覆蓋了之前的參數
foo(1, param: 2);
// 錯誤:命名參數 $param 覆蓋了之前的參數
?>