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

2023-08-16 15:35 更新

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

PHP 支持按值傳遞參數(shù)(默認(rèn)),通過引用傳遞參數(shù) 以及 默認(rèn)參數(shù)。也支持 可變長度參數(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ù)列表可以包含一個尾部的逗號,這個逗號將被忽略。這在參數(shù)列表較長或包含較長的變量名的情況下特別有用,這樣可以方便地垂直列出參數(shù)。

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

<?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 之前,這個尾部的逗號是不允許的。
)
{
// ...
}
?>

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

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

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

示例 #3 用引用傳遞函數(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ù)可以使用類似分配變量的語法定義參數(shù)的默認(rèn)值。僅當(dāng)參數(shù)未指定時才使用默認(rèn)值;需要注意的是傳遞 null 不會分配默認(rèn)值。

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

<?php
function makecoffee($type = "cappuccino")
{
return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>

以上示例會輸出:

Making a cup of cappuccino.
Making a cup of .
Making a cup of espresso.

默認(rèn)參數(shù)值可以是標(biāo)量值、array、特殊類型 null,以及從 PHP 8.1.0 開始,使用 new ClassName() 語法的對象。

示例 #5 使用非標(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");?>

示例 #6 使用對象作為默認(rèn)值(自 PHP 8.1.0 起)

<?php
class DefaultCoffeeMaker {
public function brew() {
return 'Making coffee.';
}
}
class FancyCoffeeMaker {
public function brew() {
return 'Crafting a beautiful coffee just for you.';
}
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>

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

注意任何可選參數(shù)都應(yīng)在強(qiáng)制參數(shù)之后指定,否則可選參數(shù)不能在調(diào)用時省略。考慮以下示例:

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

<?php
function makeyogurt($container = "bowl", $flavour)
{
return "Making a $container of $flavour yogurt.\n";
}

echo makeyogurt("raspberry"); // "raspberry" 是 $container, 不是 $flavour
?>

以上示例會輸出:

Fatal error: Uncaught ArgumentCountError: Too few arguments
 to function makeyogurt(), 1 passed in example.php on line 42

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

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

<?php
function makeyogurt($flavour, $container = "bowl")
{
return "Making a $container of $flavour yogurt.\n";
}

echo makeyogurt("raspberry"); // "raspberry" 是 $flavour
?>

以上示例會輸出:

Making a bowl of raspberry yogurt.

自 PHP 8.0.0 起,命名參數(shù)可用于跳過多個可選參數(shù)。

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

<?php
function makeyogurt($container = "bowl", $flavour = "raspberry", $style = "Greek")
{
return "Making a $container of $flavour $style yogurt.\n";
}

echo makeyogurt(style: "natural");
?>

以上示例會輸出:

Making a bowl of raspberry natural yogurt.

自 PHP 8.0.0 起,棄用在可選參數(shù)之后聲明強(qiáng)制參數(shù)。這通??梢酝ㄟ^刪除默認(rèn)值來解決,因為它永遠(yuǎn)不會被使用。唯一的例外是 Type $param = null 類型的參數(shù),其中默認(rèn) null 使得該類型可以隱式為 null。這種做法依然允許,但是推薦使用顯式可為 null 類型代替。

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

<?php
function foo($a = [], $b) {} // 默認(rèn)不使用;自 PHP 8.0.0 起棄用
function foo($a, $b) {} // 功能相同,無棄用通知

function bar(A $a = null, $b) {} // 仍然允許;但 $a 強(qiáng)制但可以為 null
function bar(?A $a, $b) {} // 推薦
?>
注意: 自 PHP 7.1.0 起,省略未指定默認(rèn)值的參數(shù)會原因引發(fā) ArgumentCountError;在此之前的版本會引發(fā)警告。
注意: 傳引用的參數(shù)也可以有默認(rèn)值。

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

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

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

包含 ... 的參數(shù),會轉(zhuǎn)換為指定參數(shù)變量的一個 array:

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

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

echo sum(1, 2, 3, 4);
?>

以上示例會輸出:

10

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

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

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

echo add(...[1, 2])."\n";

$a = [1, 2];
echo add(...$a);
?>

以上示例會輸出:

3
3

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

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

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

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

// 這將會失敗,因為 null 不是 DateInterval 對象。
echo total_intervals('d', null);
?>

以上示例會輸出:

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ù)傳遞 引用變量,通過在 ... 前加上一個 (&) 符號來實現(xiàn)。

舊版本的 PHP

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

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

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

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

echo sum(1, 2, 3, 4);
?>

以上示例會輸出:

10

命名參數(shù)

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

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

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

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

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

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

<?php
// 使用順序傳遞參數(shù):
array_fill(0, 100, 50);

// 使用命名參數(shù):
array_fill(start_index: 0, count: 100, value: 50);
?>

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

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

<?php
array_fill(value: 50, count: 100, start_index: 0);
?>

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

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

<?php
htmlspecialchars($string, double_encode: false);
// 等價于
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>

傳遞多個相同參數(shù)將會導(dǎo)致 Error 異常。

示例 #19 傳遞多個相同參數(shù)將會導(dǎo)致拋出 Error

<?php
function foo($param) { ... }

foo(param: 1, param: 2);
// 錯誤:命名參數(shù) $param 覆蓋了之前的參數(shù)
foo(1, param: 2);
// 錯誤:命名參數(shù) $param 覆蓋了之前的參數(shù)
?>

自 PHP 8.1.0 起,可以在解包參數(shù)后面使用命名參數(shù)。命名參數(shù)不能覆蓋已解包的參數(shù)。

示例 #20 解包后使用命名參數(shù)

<?php
function foo($a, $b, $c = 3, $d = 4) {
return $a + $b + $c + $d;
}

var_dump(foo(...[1, 2], d: 40)); // 46
var_dump(foo(...['b' => 2, 'a' => 1], d: 40)); // 46

var_dump(foo(...[1, 2], b: 20)); // Fatal error。命名參數(shù) $b 覆蓋之前的參數(shù)
?>


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號