Menu

PHP 函数:定义、返回值、参数和类型

用 function name($param) { return $value; } 定义 PHP 函数。本文讲解返回值、默认参数、命名参数、引用传递、strict_types 类型声明、可空类型和联合类型,以及可变参数 ...$args。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

PHP 函数由 function 关键字、函数名、参数列表和函数体组成;return 把一个值返回给调用方。function add(int $a, int $b): int { return $a + $b; } 定义了函数,add(2, 3) 调用它并返回 5。

参数前面的 string 和 int 是类型声明,括号后面的 : string 是返回类型。两者都是可选的,但它们能尽早发现错误,也说明了函数期望接收什么。

返回值与返回多个值

return 会立即结束函数。没有 return 的函数,或者只写了 return; 的函数,返回 null;如果函数只是为了它的副作用而被调用,就声明 : void。函数只返回一个值,但这个值可以是数组,你可以在调用方解构它:

[...] = 的其他写法见数组解构。

默认参数和命名参数

带有 = value 的参数是可选的:调用方可以省略它。可选参数放在必需参数之后。从 PHP 8.0 开始,命名参数让调用方可以按名字传递任意参数,这样你就能跳过不需要的可选参数。

命名参数也能让内置函数的调用更易读:str_pad('7', 3, '0', pad_type: STR_PAD_LEFT)。参数名会成为函数公开接口的一部分,所以重命名参数可能会破坏使用参数名调用的代码。

引用传递

通常 PHP 传递的是每个实参的副本,所以函数无法修改调用方的变量。参数前的 & 会传递变量本身。像 sort() 这样的内置函数就是这样工作的。

返回一个新值通常比修改参数更清晰。只有当函数确实要原地修改某个东西时,才使用引用。

类型声明和 strict_types

默认情况下,PHP 会尽可能把实参转换成声明的类型:add("5", 3) 会把 "5" 变成 5。在文件最顶部写上 declare(strict_types=1);,就会对该文件中发出的调用关闭这种转换,于是类型不对时会抛出 TypeError,而不是被转换。

去掉 declare 这一行,同样的调用会输出 8。不是数字的字符串(比如 "five")在两种模式下都会抛出 TypeError。

参数和返回值可以声明的类型:

never 是一种返回类型,用于总是抛出异常或退出的函数。类名和接口名也可以用作类型。

用 ...$args 接收可变数量的参数

...$numbers 会把任意数量的实参收集到一个数组里。在调用方使用同样的 ...,则会把数组展开成多个独立的实参。

在函数内使用外部变量

函数有自己的作用域。在函数外定义的变量在函数内不可见,这常常让从 JavaScript 转过来的人感到意外:

<?php
$taxRate = 0.2;

function priceWithTax(float $price): float
{
    return $price * (1 + $taxRate);   // $taxRate is undefined here
}
Warning: Undefined variable $taxRate in /path/to/index.php on line 6

而且函数返回的是不含税的价格。正确的做法是把这个值作为参数传进去。这样函数依赖什么一目了然,也便于测试:

global 关键字也能用,但它会把依赖关系藏起来;变量作用域介绍了它。对于传给其他函数的短小函数,比如 array_map() 的回调,请看匿名函数,它可以用 use 捕获外部变量。

常见问题

PHP 中怎么定义函数?

使用 function 关键字,加上函数名、括号里的参数和函数体:function add(int $a, int $b): int { return $a + $b; }。调用方式是 add(2, 3)。函数名不区分大小写,在文件顶层定义的函数可以在定义它的那一行之前调用。

PHP 函数怎么返回多个值?

返回一个数组,然后解构它:function minMax(array $a): array { return [min($a), max($a)]; },再写 [$min, $max] = minMax([3, 1, 4]);。如果想按名字取结果,就返回关联数组,并使用 ['min' => $min] = ...。

declare(strict_types=1) 有什么作用?

它会关闭从该文件发出的调用中的自动类型转换,所以把 "5" 传给 int 参数会抛出 TypeError,而不是把它转换成 5。它必须是文件中的第一条语句,并且只影响这个文件。

PHP 中的命名参数是什么?

从 PHP 8.0 开始,你可以按参数名传递实参:htmlspecialchars($s, double_encode: false)。命名参数可以放在位置参数之后,顺序任意,还能让你跳过不想改动的可选参数。

PHP 中怎么按引用传递变量?

在参数前加上 &:function addOne(int &$n): void { $n++; }。这样函数会修改调用方的变量。不加 & 时,PHP 传递的是副本,调用方的变量保持不变。

Coddy 编程语言插图

和 Coddy 一起学编程

开始