通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。参数是从左向右求值的。
PHP 支持按值传递参数(默认),通过引用传递参数 以及 默认参数。也支持 可变长度参数列表。
Example #1 向函数传递数组
<?php
function takes_array($input)
{
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
?>
默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。
如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面加上符号 &:
Example #2 用引用传递函数参数
<?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++ 风格的标量参数默认值,如下所示:
Example #3 在函数中使用默认参数
<?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
作为默认参数,例如:
Example #4 使用非标量类型作为默认参数
<?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");
?>
默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。
注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作。考虑下面的代码片断:
Example #5 函数默认参数的不正确用法
<?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 .
现在,比较上面的例子和这个例子:
Example #6 函数默认参数正确的用法
<?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.
Note: 自 PHP 5 起,传引用的参数也可以有默认值。
Note:
在 PHP 5 中,类型声明也被称为类型提示。
类型声明允许函数在调用时要求参数为特定类型。 如果给出的值类型不对,那么将会产生一个错误: 在 PHP 5 中,这将是一个可恢复的致命错误,而在 PHP 7 中将会抛出一个 TypeError 异常。
为了指定一个类型声明,类型应该加到参数名前。这个声明可以通过将参数的默认值设为 NULL
来实现允许传递 NULL
。
类型 | 描述 | 最小可用 PHP 版本 |
---|---|---|
Class/interface name |
参数为指定类或接口的 instanceof 。
|
PHP 5.0.0 |
self |
参数为当前类的 instanceof 。可以为类或接口。
|
PHP 5.0.0 |
array | 参数必须为 array。 | PHP 5.1.0 |
callable | 参数必须为有效的 callable。 | PHP 5.4.0 |
bool | 参数必须为 boolean 值。 | PHP 7.0.0 |
float | 参数必须为 float 浮点数。 | PHP 7.0.0 |
int | 参数必须为 integer。 | PHP 7.0.0 |
string | 参数必须为 string。 | PHP 7.0.0 |
iterable |
参数必须为 array 或 Traversable 的 instanceof 。
|
PHP 7.1.0 |
object |
参数必须为 object。 | PHP 7.2.0 |
Aliases for the above scalar types are not supported. Instead, they are
treated as class or interface names. For example, using
boolean
as a parameter or return type will require
an argument or return value that is an instanceof
the class or
interface boolean
, rather than of type
bool:
<?php
function test(boolean $param) {}
test(true);
?>
以上例程会输出:
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1
Example #7 基类类型声明
<?php
class C {}
class D extends C {}
// This doesn't extend C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
以上例程会输出:
C D Fatal error: Uncaught TypeError: Argument 1 passed to f() must be an instance of C, instance of E given, called in - on line 14 and defined in -:8 Stack trace: #0 -(14): f(Object(E)) #1 {main} thrown in - on line 8
Example #8 接口类类型声明
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// This doesn't implement I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
以上例程会输出:
C Fatal error: Uncaught TypeError: Argument 1 passed to f() must implement interface I, instance of E given, called in - on line 13 and defined in -:8 Stack trace: #0 -(13): f(Object(E)) #1 {main} thrown in - on line 8
Example #9 Typed pass-by-reference Parameters
Declared types of reference parameters are checked on function entry, but not when the function returns, so after the function had returned, the argument's type may have changed.
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
以上例程的输出类似于:
int(1) Fatal error: Uncaught TypeError: Argument 1 passed to array_baz() must be of the type array, int given, called in %s on line %d
Example #10 可空类型声明
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
以上例程会输出:
object(C)#1 (0) { } NULL
默认情况下,如果能做到的话,PHP 将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是 string,但传入的是 integer,最终函数得到的将会是一个 string 类型的值。
可以基于每一个文件开启严格模式。在严格模式中,只有一个与类型声明完全相符的变量才会被接受,否则将会抛出一个 TypeError。唯一的一个例外是可以将 integer 传给一个期望 float 的函数。
使用 declare
语句和 strict_types
声明来启用严格模式:
启用严格模式同时也会影响 返回值类型声明。
Note:
严格类型适用于在 启用严格模式的文件内 的函数调用,而不是在那个文件内声明的函数。 一个没有启用严格模式的文件内调用了一个在启用严格模式的文件中定义的函数,那么将会遵循调用者的偏好(弱类型),而这个值将会被转换。
Note:
严格类型仅用于标量类型声明,也正是因为如此,这需要 PHP 7.0.0 或更新版本,因为标量类型声明也是在那个版本中添加的。
Example #11 严格类型
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
以上例程会输出:
int(3) Fatal error: Uncaught TypeError: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 9 and defined in -:4 Stack trace: #0 -(9): sum(1.5, 2.5) #1 {main} thrown in - on line 4
Example #12 弱类型转换
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// These will be coerced to integers: note the output below!
var_dump(sum(1.5, 2.5));
?>
以上例程会输出:
int(3) int(3)
Example #13 捕捉 TypeError
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
?>
以上例程会输出:
int(3) Error: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 10
PHP 在用户自定义函数中支持可变数量的参数列表。在 PHP 5.6 及以上的版本中,由
...
语法实现;在 PHP 5.5 及更早版本中,使用函数
func_num_args(),func_get_arg(),和
func_get_args() 。
...
in PHP 5.6+
PHP 5.6 之后的版本中,包含
...
的参数,会转换为指定参数变量的一个数组,见以下示例:
Example #14 使用 ...
来访问变量参数
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
以上例程会输出:
10
也可以使用 ...
语法来传递 array 或
Traversable 做为参数到函数中:
Example #15 使用 ...
来传递参数
<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>
以上例程会输出:
3 3
You may specify normal positional arguments before the
...
token. In this case, only the trailing arguments
that don't match a positional argument will be added to the array
generated by ...
.
It is also possible to add a
type hint before the
...
token. If this is present, then all arguments
captured by ...
must be objects of the hinted class.
Example #16 输入提示的变量参数
<?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';
// 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
Finally, you may also pass variable arguments
by reference by
prefixing the ...
with an ampersand
(&
).
不需要特殊的语法来声明一个函数是可变的;但是访问函数的参数必须使用 func_num_args(), func_get_arg() 和 func_get_args() 函数。
上面的第一个例子在 PHP 5.5 和更早的版本中的实现如下:
Example #17 在 PHP 5.5 和更早的版本中访问可变参数
<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
以上例程会输出:
10