函数
函数是一个可重复使用的代码块,在给定输入的情况下执行一些操作,并返回一些结果。你已经知道一些预定义函数,如 empty
、in_array
或 var_dump
。这些函数是 PHP 自带的,所以你不必重新发明轮子,但你可以很容易地创建自己的函数。在确定应用程序中需要多次执行的部分或只是为了封装某些功能时,可以定义函数。
函数声明
声明函数意味着将其写下来,以便以后使用。函数有一个名称,接受一些参数,并有一个代码块。函数还可以定义返回值的类型。函数名必须遵循与变量名相同的规则,即必须以字母或下划线开头,可以包含任何字母、数字或下划线。不能使用保留字。
我们来看一个简单的例子:
function addNumbers($a, $b) {
$sum = $a + $b;
return $sum;
}
$result = addNumbers(2, 3);
前面的函数名为 addNumbers
,它有两个参数: $a
和 $b
。代码块定义了一个新变量 $sum
,它是两个参数的总和,然后用 return
返回其内容。要使用该函数,只需调用它的名称,同时发送所有需要的参数,如高亮显示行所示。
PHP 不支持重载函数。重载是指声明两个或多个名称相同但参数不同的函数。如您所见,您可以在不知道参数类型的情况下声明参数,因此 PHP 无法决定使用哪个函数。
另一个需要注意的地方是变量的作用域。我们在代码块中声明了一个变量 $sum
,因此一旦函数结束,这个变量将不再被访问。也就是说,在函数内部声明的变量的作用域仅限于函数本身。此外,如果在函数外部声明了变量 $sum
,它也不会受到任何影响,因为除非我们将其作为参数发送,否则函数无法访问该变量。
函数参数
函数通过参数从外部获取信息。您可以定义任意数量的参数,包括 0(无)。这些参数至少需要一个名称,以便在函数内部使用;不能有两个参数同名。调用函数时,需要按照声明的顺序发送参数。
函数可能包含可选参数,也就是说,您不必强制为这些参数赋值。在声明函数时,需要为这些参数提供默认值。因此,如果用户没有提供参数值,函数将使用默认值。
function addNumbers($a, $b, $printResult = false) {
$sum = $a + $b;
if ($printResult) {
echo 'The result is ' . $sum;
}
return $sum;
}
$sum1 = addNumbers(1, 2);
$sum1 = addNumbers(3, 4, false);
$sum1 = addNumbers(5, 6, true); // it will print the result
上一个示例中的新函数包含两个必选参数和一个可选参数。可选参数的默认值为 false
,在函数中正常使用。如果用户提供 true
作为第三个参数,函数将打印求和的结果,而这只发生在第三次调用函数时。在前两次中,$printResult
被设置为 false
。
函数接收的参数只是用户提供的值的副本。也就是说,如果在函数内部修改这些参数,将不会影响原始值。这一功能被称为按值发送参数。让我们来看一个例子:
function modify($a) {
$a = 3;
}
$a = 2;
modify($a);
var_dump($a); // prints 2
我们声明了一个值为 2 的变量 $a
,然后调用 modify
方法发送该 $a
。modify
方法修改了参数 $a
,将其值设置为 3,但这并不影响 $a
的原始值,正如 var_dump
所示,它仍然是 2。
如果要真正改变调用中使用的原始变量的值,则需要通过引用来传递参数。为此,需要在声明函数时在参数前添加一个 &
:
function modify(&$a) {
$a = 3;
}
现在,在调用函数 modify
时,$a
将始终为 3。
按值参数与按引用参数
PHP 允许这样做,事实上,PHP 的一些本地函数使用引用参数。还记得数组排序功能吗?它们并不返回排序后的数组,而是对提供的数组进行排序。但使用参数引用是一种混淆开发人员的方法。通常,当有人使用函数时,他们期望得到一个结果,而不希望自己提供的参数被修改。因此,请尽量避免这样做;人们会感激不尽的! |
返回语句
您可以在函数中使用任意多的 return
语句,但 PHP 会在发现返回语句时立即退出函数。这意味着如果有两个连续的 return
语句,第二个将永远不会被执行。不过,如果在条件中使用多个返回语句,还是很有用的。在 functions.php
文件中添加此函数:
function loginMessage() {
if (isset($_COOKIE['username'])) {
return "You are " . $_COOKIE['username'];
} else {
return "You are not authenticated.";
}
}
让我们在 index.php
文件中使用最后一个示例,替换高亮显示的内容(注意,为了节省一些空间,我用 //...
替换了大部分没有改动的代码):
//...
<body>
<p><?php echo loginMessage(); ?></p>
<?php if (isset($_GET['title']) && isset($_GET['author'])): ?>
//...
此外,如果不希望函数返回任何内容,也可以省略 return
语句。在这种情况下,函数将在代码块结束时结束。
类型提示和返回类型
随着 PHP 7 的发布,该语言允许开发人员更具体地说明函数的获取和返回。您可以—始终是可选的—指定函数所需的参数类型(类型提示),以及函数将返回的结果类型(返回类型)。让我们先来看一个例子:
<?php
declare(strict_types=1);
function addNumbers(int $a, int $b, bool $printSum): int {
$sum = $a + $b;
if ($printSum) {
echo 'The sum is ' . $sum;
}
return $sum;
}
addNumbers(1, 2, true);
addNumbers(1, '2', true); // it fails when strict_types is 1
addNumbers(1, 'something', true); // it always fails
前面的这个函数说明,参数需要是整数、整型和布尔型,而结果将是一个整数。现在,我们知道 PHP 具有类型杂耍功能,因此它通常可以将一种类型的值转换为另一种类型的等价值,例如,字符串 "2" 可以用作整数 2。要阻止 PHP 对函数的参数和结果使用类型戏法,可以声明严格类型(strict_types
)指令,如第一个突出显示的行所示。该指令必须声明在要强制执行该行为的每个文件的顶部。
三次调用的工作原理如下:
-
第一次调用发送了两个整数和一个布尔值,这正是函数所期望的,因此无论
string_types
的值如何,它都能正常工作。 -
第二次调用发送了一个整数、一个字符串和一个布尔值。字符串有一个有效的整数值,因此如果 PHP 允许使用类型戏法,调用就会正常解决。但在本例中,由于文件顶部的声明,调用会失败。
-
第三次调用总是失败,因为字符串 "something" 无法转换为有效的整数。
让我们尝试在项目中使用函数。在 index.php
中,我们有一个 foreach
循环,用于遍历书籍并打印出来。循环内部的代码很难理解,因为它是 HTML 和 PHP 的混合体,而且还有一个条件。让我们尝试将循环内部的逻辑抽象为一个函数。首先,创建新的 functions.php
文件,内容如下:
<?php
function printableTitle(array $book): string {
$result = '<i>' . $book['title'] . '</i> - ' . $book['author'];
if (!$book['available']) {
$result .= ' <b>Not available</b>';
}
return $result;
}
该文件将包含我们的函数。第一个函数是 printableTitle
,它接收一个代表一本书的数组,并用 HTML 创建一个能很好地表示这本书的字符串。代码与之前的相同,只是封装在一个函数中。
现在,index.php
必须包含 functions.php
文件,然后在循环中使用该函数。让我们看看如何操作:
<?php require_once 'functions.php' ?>
<!DOCTYPE html>
<html lang="en">
//...
?>
<ul>
<?php foreach ($books as $book): ?>
<li><?php echo printableTitle($book); ?> </li>
<?php endforeach; ?>
</ul>
//...
现在,我们的循环看起来更简洁了,对吗?另外,如果我们需要在其他地方打印书名,我们可以重复使用这个函数,而不是重复代码!