函數(shù)的參數(shù)

通過參數(shù)列表可以傳遞信息到函數(shù),即以逗號(hào)作為分隔符的表達(dá)式列表。函數(shù)在實(shí)際調(diào)用之前,值參數(shù)是從左向右求值的(及早求值)。

PHP 支持按值傳遞參數(shù)(默認(rèn)),通過引用傳遞參數(shù) 以及 默認(rèn)參數(shù)。也支持 可變長(zhǎng)度參數(shù)列表命名參數(shù)。

示例 #1 向函數(shù)傳遞數(shù)組

<?php
function takes_array($input)
{
    echo 
"$input[0] + $input[1] = "$input[0]+$input[1];
}
?>

從 PHP 8.0.0 開始,函數(shù)參數(shù)列表可以包含一個(gè)尾部的逗號(hào),這個(gè)逗號(hào)將被忽略。這在參數(shù)列表較長(zhǎng)或包含較長(zhǎng)的變量名的情況下特別有用,這樣可以方便地垂直列出參數(shù)。

示例 #2 函數(shù)參數(shù)使用尾部逗號(hào)

<?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è)尾部的逗號(hào)是不允許的。
)
{
    
// ...
}
?>

從 PHP 8.0.0 開始,廢棄在可選參數(shù)后聲明強(qiáng)制參數(shù)??梢酝ㄟ^刪除默認(rèn)值來解決。 此規(guī)則一個(gè)例外是 Type $param = null 形式的參數(shù), 其中 null 默認(rèn)值使類型隱性允許為空。 這種做法依然允許,但是推薦使用顯性可為 null 的類型代替。

示例 #3 強(qiáng)制參數(shù)后聲明可選參數(shù)

<?php
function foo($a = [], $b) {} // 之前
function foo($a$b) {}      // 之后

function bar(A $a null$b) {} // 同時(shí)可用
function bar(?A $a$b) {}       // 官方推薦的寫法
?>

通過引用傳遞參數(shù)

默認(rèn)情況下,函數(shù)參數(shù)通過值傳遞(因而即使在函數(shù)內(nèi)部改變參數(shù)的值,它并不會(huì)改變函數(shù)外部的值)。如果希望允許函數(shù)修改它的參數(shù)值,必須通過引用傳遞參數(shù)。

如果想要函數(shù)的一個(gè)參數(shù)總是通過引用傳遞,可以在函數(shù)定義中該參數(shù)的前面加上符號(hào) &:

示例 #4 用引用傳遞函數(shù)參數(shù)

<?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.'
?>

默認(rèn)參數(shù)的值

函數(shù)可以定義 C++ 風(fēng)格的標(biāo)量參數(shù)默認(rèn)值,如下所示:

示例 #5 在函數(shù)中使用默認(rèn)參數(shù)

<?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 還允許使用數(shù)組 array 和特殊類型 null 作為默認(rèn)參數(shù),例如:

示例 #6 使用非標(biāo)量類型作為默認(rèn)參數(shù)

<?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");
?>

默認(rèn)值必須是常量表達(dá)式,不能是諸如變量,類成員,或者函數(shù)調(diào)用等。

注意當(dāng)使用默認(rèn)參數(shù)時(shí),任何默認(rèn)參數(shù)必須放在任何非默認(rèn)參數(shù)的右側(cè);否則,函數(shù)將不會(huì)按照預(yù)期的情況工作??紤]下面的代碼片斷:

示例 #7 函數(shù)默認(rèn)參數(shù)的不正確用法

<?php
function makeyogurt($type "acidophilus"$flavour)
{
    return 
"Making a bowl of $type $flavour.\n";
}

echo 
makeyogurt("raspberry");   // 不會(huì)按照預(yù)期工作
?>

以上例程會(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 .

現(xiàn)在,比較上面的例子和這個(gè)例子:

示例 #8 函數(shù)默認(rèn)參數(shù)正確的用法

<?php
function makeyogurt($flavour$type "acidophilus")
{
    return 
"Making a bowl of $type $flavour.\n";
}

echo 
makeyogurt("raspberry");   // 按預(yù)期工作
?>

以上例程會(huì)輸出:

Making a bowl of acidophilus raspberry.

注意: 傳引用的參數(shù)也可以有默認(rèn)值。

可變數(shù)量的參數(shù)列表

PHP 在用戶自定義函數(shù)中支持可變數(shù)量的參數(shù)列表。由 ... 語法實(shí)現(xiàn)。

注意: 還可以使用以下函數(shù)來獲取可變參數(shù) func_num_args()func_get_arg()func_get_args(),不建議使用此方式,請(qǐng)使用 ... 來替代。

包含 ... 的參數(shù),會(huì)轉(zhuǎn)換為指定參數(shù)變量的一個(gè)數(shù)組,見以下示例:

示例 #9 使用 ... 來訪問變量參數(shù)

<?php
function sum(...$numbers) {
    
$acc 0;
    foreach (
$numbers as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

以上例程會(huì)輸出:

10

也可以使用 ... 語法來傳遞 arrayTraversable 做為參數(shù)到函數(shù)中:

示例 #10 使用 ... 來傳遞參數(shù)

<?php
function add($a$b) {
    return 
$a $b;
}

echo 
add(...[12])."\n";

$a = [12];
echo 
add(...$a);
?>

以上例程會(huì)輸出:

3
3

你可以在 ... 前指定正常的位置參數(shù)。在這種情況下,只有不符合位置參數(shù)的尾部參數(shù)才會(huì)被添加到 ... 生成的數(shù)組中。

你也可以在 ... 標(biāo)記前添加一個(gè) 類型聲明。如果存在這種情況,那么 ... 捕獲的所有參數(shù)都必須匹配參數(shù)類型。

示例 #11 輸入提示的變量參數(shù)

<?php
function total_intervals($unitDateInterval ...$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ì)失敗,因?yàn)?nbsp;null 不是 DateInterval 對(duì)象。
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

最后,你還可以給參數(shù)傳遞 引用變量,通過在 ... 前加上一個(gè) (&) 符號(hào)來實(shí)現(xiàn)。

舊版本的 PHP

不需要特殊的語法來聲明一個(gè)函數(shù)是可變的;但是訪問函數(shù)的參數(shù)必須使用 func_num_args(), func_get_arg()func_get_args() 函數(shù)。

上面的第一個(gè)例子在早期 PHP 版本中的實(shí)現(xiàn)如下:

示例 #12 在 PHP 早期版本中訪問可變參數(shù)

<?php
function sum() {
    
$acc 0;
    foreach (
func_get_args() as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

以上例程會(huì)輸出:

10

命名參數(shù)

PHP 8.0.0 開始引入了命名參數(shù)作為現(xiàn)有位置參數(shù)的擴(kuò)展。命名參數(shù)允許根據(jù)參數(shù)名而不是參數(shù)位置向函數(shù)傳參。這使得參數(shù)的含義自成體系,參數(shù)與順序無關(guān),并允許任意跳過默認(rèn)值。

命名參數(shù)通過在參數(shù)名前加上冒號(hào)來傳遞。允許使用保留關(guān)鍵字作為參數(shù)名。參數(shù)名必須是一個(gè)標(biāo)識(shí)符,不允許動(dòng)態(tài)指定。

示例 #13 命名參數(shù)的語法

<?php
myFunction
(paramName$value);
array_foobar(array: $value);

// 不支持。
function_name($variableStoringParamName$value);
?>

示例 #14 通過位置傳參與命名參數(shù)的對(duì)比

<?php
// 使用順序傳遞參數(shù):
array_fill(010050);

// 使用命名參數(shù):
array_fill(start_index0count100value50);
?>

指定參數(shù)的傳遞順序并不重要。

示例 #15 參數(shù)順序不同的示例(同上例)

<?php
array_fill
(value50count100start_index0);
?>

命名參數(shù)也可以與位置參數(shù)相結(jié)合使用。此種情況下,命名參數(shù)必須在位置參數(shù)之后。也可以只指定一個(gè)函數(shù)的部分可選參數(shù),而不考慮它們的順序。

示例 #16 命名參數(shù)與位置參數(shù)結(jié)合使用

<?php
htmlspecialchars
($stringdouble_encodefalse);
// 等價(jià)于
htmlspecialchars($stringENT_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(param1param2);
// 錯(cuò)誤:命名參數(shù) $param 覆蓋了之前的參數(shù)
foo(1param2);
// 錯(cuò)誤:命名參數(shù) $param 覆蓋了之前的參數(shù)
?>