本教程将向您介绍 php 中匿名函数的特性和用途。您还将了解 PHP 中较新的箭头函数语法。
PHP中的匿名函数
每当我们在 PHP 中定义一个函数时,我们通常也会为其提供一个名称。该名称用于在以后需要时调用该函数。但是,有时只在一个地方需要一个函数,而在其他地方不需要。假设您正在处理一个需要您编写大约 50 个或更多此类函数的大型项目。
在这种情况下,将函数定义放在需要的地方要容易得多,而不必担心为函数命名。这些类型的函数称为匿名函数。当您处理只有四到五行长的函数时,它们特别有用。
使用匿名函数实现回调
匿名函数最常见的用途之一是作为回调。回调函数由主函数调用,以根据您提供的逻辑执行任务。我们可以使用内置和用户定义的函数作为回调。以下是此类功能的示例:
<?php $numbers = [12, 18, 5, 11, 10, 95, 3]; $multiple_five = array_filter($numbers, function($n) { return $n%5 == 0; }); print_r($multiple_five); /* Array ( [2] => 5 [4] => 10 [5] => 95 ) */ ?>
在上面的代码中,我们只是从给定的数字数组中返回 5 的倍数。第二个参数array_filter()
是我们的回调函数。如您所见,它执行检查一个数是否可被 5 整除的琐碎任务。如果没有匿名函数,我们将不得不在其他地方定义这个函数并想出一个不冲突的名称。
将匿名函数分配给变量
我们通常为我们在 PHP 中定义的任何函数分配一个名称。此名称用于稍后在需要时调用该函数。但是,匿名函数没有任何名称。如果需要,这会使我们以后很难打电话给他们。
匿名函数的一个很好的特性是我们可以将它们分配给变量或将它们存储在数字或关联数组中。之后,我们可以使用变量名调用这些函数。这是一个例子:
<?php $padded = function($word) { echo str_pad($word, 10, "_", STR_PAD_BOTH); }; $word_funcs = [ 'capital' => function($word) { echo strtoupper($word); }, 'reversed' => function($word) { echo strrev($word); }, 'rotated' => function($word) { echo str_rot13($word); }, ]; $padded("banana"); // __banana__ $word_funcs['capital']("mango"); // MANGO ?>
正如您在上面的代码中看到的那样,这些匿名函数可以分配给变量并像常规函数一样调用。
匿名函数可以从父作用域继承变量
在我们之前的一篇名为“了解 PHP 中的变量作用域”的文章中,我们详细介绍了变量作用域。基本上,PHP 具有全局范围和函数级范围。您不能访问在函数内其他地方定义的变量。同样,在函数内部定义的变量将无法在其外部访问。
在函数内部访问外部变量的一种方法是使用global
关键字。但是,这种方法有一些缺点,因为从长远来看,它会使代码维护变得更加困难。
PHP 还有一个特殊的use
关键字,允许您从匿名函数内的父作用域访问变量。让我们通过一些示例来了解它们之间global
的区别:use
<?php // Global Scope $pad = '@'; $full_length = 20; function parent_function() { // Parent Scope $pad = '#'; $full_length = 16; function padding($word) { global $pad; global $full_length; echo str_pad($word, $full_length, $pad, STR_PAD_BOTH); $full_length = 40; }; padding('banana'); } parent_function(); // @@@@@@@banana@@@@@@@ echo $full_length; // 40 ?>
在上面的例子中,我们定义了变量$pad
和$full_length
两次。当在顶部定义时,它们是全局范围的一部分。我们在函数内部再次定义了这两个变量parent_function()
。但是,它们与定义在全局范围内的变量无关,因为函数在 PHP 中有自己的范围。
当我们padding()
在关键字的帮助下在函数中使用这些变量时global
,我们实际上是在访问全局值。从 的输出中可以明显看出这一点parent_function()
。我们还能够$full_length
在函数内部更改 global 的值。
我们可以重写上面的代码来使用匿名函数和use
关键字。它看起来像下面的代码片段:
<?php // Global Scope $pad = '@'; $full_length = 20; function parent_function() { // Parent Scope $pad = '#'; $full_length = 16; $padding = function($word) use ($pad, $full_length) { echo str_pad($word, $full_length, $pad, STR_PAD_BOTH); $full_length = 40; }; $padding('banana'); echo $full_length; // 16 } parent_function(); // #####banana##### echo $full_length; // 20 ?>
这一次,我们使填充函数匿名并$pad
在关键字$full_length
的帮助下访问。use
这些变量的值取自父作用域。从父作用域中删除变量会给你关于未定义变量的错误。
另请注意,匿名函数实际上是在使用父作用域中的变量副本。这就是为什么在$full_length
匿名函数之外的值没有改变的原因。
如果您希望这些更改反映在函数之外,您可以通过引用传递这些变量。
使匿名回调函数更加通用
在本教程的开头,我们了解到匿名函数通常用作回调。array_filter()
这已使用该功能进行了演示。在那个例子中,我们过滤掉了数组中所有不是 5 倍数的数字。这个 5 被硬编码到回调函数中。
如果我们想让我们的过滤器功能更加通用,以便它可以过滤掉不是其他值(例如 8 或 10)的倍数的数字,该怎么办?一种方法是将另一个数字作为第二个参数传递。
不幸的是,回调函数需要特定数量的参数(在本例中为一个)。因此,传递两个参数会导致错误。use
我们可以在关键字的帮助下绕过这个限制。use
正如我们在上一节中看到的,匿名函数可以使用关键字从父作用域继承变量。这是基于这一事实的回调的修改版本。
<?php $numbers = [12, 18, 5, 11, 10, 95, 3]; $factors = [2, 3, 5]; foreach($factors as $factor) { $multiples = array_filter($numbers, function($n) use ($factor) { return $n%$factor == 0; }); echo "Multiples of $factor\n"; print_r($multiples); } /* Multiples of 2 Array ( [0] => 12 [1] => 18 [4] => 10 ) Multiples of 3 Array ( [0] => 12 [1] => 18 [6] => 3 ) Multiples of 5 Array ( [2] => 5 [4] => 10 [5] => 95 ) */ ?>
我们创建了一组要过滤其倍数的因子。之后,我们使用foreach
循环遍历因子。每个因素都被传递给回调函数,以便array_filter()
为我们提供所有因素的倍数。
PHP中的箭头函数
箭头函数基本上是编写简单匿名函数的一种更短的方式。它们是在 PHP 7.4 中引入的。定义箭头函数时,关键字function
被替换为完全省略。它们只包含一个表达式,该表达式是箭头函数的返回值。fn
return
箭头函数的另一个特点是,在父作用域中定义的变量可以隐式地使用,而无需添加use
关键字。
<?php $numbers = [12, 18, 5, 11, 10, 95, 3]; $factors = [2, 3, 5]; foreach($factors as $factor) { $multiples = array_filter($numbers, fn($n) => $n%$factor == 0); echo "Multiples of $factor\n"; print_r($multiples); } /* Multiples of 2 Array ( [0] => 12 [1] => 18 [4] => 10 ) Multiples of 3 Array ( [0] => 12 [1] => 18 [6] => 3 ) Multiples of 5 Array ( [2] => 5 [4] => 10 [5] => 95 ) */ ?>
运行此代码会输出与前面的代码片段相同的值。正如我之前提到的,该变量$factor
可以在我们的箭头函数中使用,而无需添加use
关键字。
最后的想法
在本教程中,我们介绍了 PHP 中匿名函数的一些特性和用法。这包括将它们用于回调或将它们分配给变量以便稍后调用它们。我们还学习了如何访问匿名函数内部父作用域中定义的变量。后来,我们利用这个特性创建了更有用的回调函数。
- 使用匿名函数实现回调
- 将匿名函数分配给变量
- 匿名函数可以从父作用域继承变量
- 使匿名回调函数更加通用