函数的参数

通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。参数是从左向右求值的。

PHP 支持按值传递参数(默认),通过引用传递参数 以及 默认参数。也支持 可变长度参数列表命名参数

示例 #1 向函数传递数组

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

从 PHP 8.0.0 开始,函数参数列表可以包含一个尾部的逗号,这个逗号将被忽略。这在参数列表较长或包含较长的变量名的情况下特别有用,这样可以方便地垂直列出参数。

示例 #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 之前,这个尾部的逗号是不允许的。
)
{
    
// ...
}
?>

As of PHP 8.0.0, passing mandatory arguments after optional arguments is deprecated. This can generally be resolved by dropping the default value. One exception to this rule are arguments of the form Type $param = null, where the null default makes the type implicitly nullable. This usage remains allowed, though it is recommended to use an explicit nullable type instead.

示例 #3 Passing optional arguments after mandatory arguments

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

function bar(A $a null$b) {} // 同时可用
function bar(?A $a$b) {}       // 官方推荐的写法
?>

通过引用传递参数

默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。

如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面加上符号 &:

示例 #4 用引用传递函数参数

<?php
function add_some_extra(&$string)
{
    
$string .= 'and something extra.';
}
$str 'This is a string, ';
add_some_extra($str);
echo 
$str;    // outputs 'This is a string, and something extra.'
?>

默认参数的值

函数可以定义 C++ 风格的标量参数默认值,如下所示:

示例 #5 在函数中使用默认参数

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

PHP 还允许使用数组 array 和特殊类型 null 作为默认参数,例如:

示例 #6 使用非标量类型作为默认参数

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

默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。

注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作。考虑下面的代码片断:

示例 #7 函数默认参数的不正确用法

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

echo 
makeyogurt("raspberry");   // won't work as expected
?>

以上例程会输出:

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 .

现在,比较上面的例子和这个例子:

示例 #8 函数默认参数正确的用法

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

echo 
makeyogurt("raspberry");   // works as expected
?>

以上例程会输出:

Making a bowl of acidophilus raspberry.

注意: 传引用的参数也可以有默认值。

可变数量的参数列表

PHP 在用户自定义函数中支持可变数量的参数列表。由 ... 语法实现。

注意: 还可以使用以下函数来获取可变参数 func_num_args()func_get_arg()func_get_args(),不建议使用此方式,请使用 ... 来替代。

包含 ... 的参数,会转换为指定参数变量的一个数组,见以下示例:

示例 #9 使用 ... 来访问变量参数

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

echo 
sum(1234);
?>

以上例程会输出:

10

也可以使用 ... 语法来传递 arrayTraversable 做为参数到函数中:

示例 #10 使用 ... 来传递参数

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

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

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

以上例程会输出:

3
3

你可以在 ... 前指定正常的位置参数。在这种情况下,只有不符合位置参数的尾部参数才会被添加到 ... 生成的数组中。

你也可以在 ... 标记前添加一个 类型声明。如果存在这种情况,那么 ... 捕获的所有参数必须是提示类的对象。

示例 #11 输入提示的变量参数

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

// This will fail, since null isn't a DateInterval object.
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

最后,你还可以给参数传递 引用变量,通过在 ... 前加上一个 (&) 符号来实现。

旧版本的 PHP

不需要特殊的语法来声明一个函数是可变的;但是访问函数的参数必须使用 func_num_args(), func_get_arg()func_get_args() 函数。

上面的第一个例子在早期 PHP 版本中的实现如下:

示例 #12 在 PHP 早期版本中访问可变参数

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

echo 
sum(1234);
?>

以上例程会输出:

10

命名参数

PHP 8.0.0 开始引入了命名参数作为现有位置参数的扩展。命名参数允许根据参数名而不是参数位置向函数传参。这使得参数的含义自成体系,参数与顺序无关,并允许任意跳过默认值。

命名参数通过在参数名前加上冒号来传递。允许使用保留关键字作为参数名。参数名必须是一个标识符,不允许动态指定。

示例 #13 命名参数的语法

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

// NOT supported.
function_name($variableStoringParamName$value);
?>

示例 #14 通过位置传参与命名参数的对比

<?php
// 使用顺序传递参数:
array_fill(010050);

// 使用命名参数:
array_fill(start_index0count100value50);
?>

指定参数的传递顺序并不重要。

示例 #15 参数顺序不同的示例(同上例)

<?php
array_fill
(value50count100start_index0);
?>

命名参数也可以与位置参数相结合使用。此种情况下,命名参数必须在位置参数之后。也可以只指定一个函数的部分可选参数,而不考虑它们的顺序。

示例 #16 命名参数与位置参数结合使用

<?php
htmlspecialchars
($stringdouble_encodefalse);
// 等价于
htmlspecialchars($stringENT_COMPAT 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);
// Error: Named parameter $param overwrites previous argument
foo(1param2);
// Error: Named parameter $param overwrites previous argument
?>