如何在 PHP 中使用箭头函数?

Posted

技术标签:

【中文标题】如何在 PHP 中使用箭头函数?【英文标题】:How to use arrow functions in PHP? 【发布时间】:2019-11-01 13:43:16 【问题描述】:

我了解了arrow functions in php 7.4。我试过像这样使用它们

<?php
$num = 1;
$arrowfunction = () => 
   return $num + 1;

echo $arrowfunction();

因为我在拉取请求中看到了=&gt; 运算符。就像javascript一样。

我希望输出为“2”,但这不起作用!我得到了

解析错误:语法错误,第 3 行 /test.php 中的意外 ')'

【问题讨论】:

这个问题(及其答案)对我很有帮助。我没有意识到 7.4 有箭头功能。 首先肯定它必须是一个主题问题吗?这是一种广泛的方式。 There is a ton of useful information in the RFC 直接从您链接的 PR 链接。 我认为这应该被添加到Reference — What does this symbol mean in PHP? 而不是新的问答。 @JohnConde 这是我脑海中出现的第一个想法,但它会造成一定程度的混乱,因为我们有很多解决箭头符号的答案***.com/questions/1241819***.com/questions/1655336***.com/questions/4758791所以我想这需要一个新的问答 【参考方案1】:

PHP 中的箭头函数是在 PHP 7.4 中引入的。它们略有不同

fn 关键字

新的fn 关键字是now a reserved keyword。

以前,我们继续使用function关键字。

$add = function ($valone,$valtwo) 
    return $valone + $valtwo;
;
$add(1,2) // 3

随着新箭头函数的出现:

$add = fn($valone,$valtwo) => $valone + $valtwo;
$add(1,2) // 3

父范围

之前,我们必须使用关键字use从父作用域中引入变量

$y = 1;
$fn = function ($x) use ($y) 
    return $x + $y;
;
echo $fn(2); // 3

父作用域中定义的表达式将被隐式按值捕获。

$y = 1;
$fn = fn($x) => $x + $y;
echo $fn(2); // 3

以上内容适用于类方法中的$this变量。

class foo 
   public function test() 
       $context = fn() => var_dump($this);
       $context(); 
   

$test = new foo();
$test->test();  // object(foo)#1 (0)  

就像之前一样,我们使用use关键字从父作用域中获取变量来执行我们的操作,所以这意味着我们不能将函数中的变量值写入上层作用域。

$y = 1;
$fn = fn() => $y++;
$fn(); // Has no effect
echo $y  // 1

如果我们想从闭包中分配另一个变量的值,那么这也行不通

$y = 1;
$f = 0;
$fn = fn() => $f = $y + 1;
$fn();
echo $f; // 0

函数签名

这在 PHP 中是全新的,它允许我们定义函数的类型、变量和函数返回的值

fn(int $x) => $x; // the argument type must be (int)
fn(): int => $x; // type of return value (int)

调用函数时,如果定义的参数类型没有放在参数中,则会引发错误。使用TypeError 类型可以捕获错误

$var = 10;
$int_fn = fn(int $x): int => $x;
var_dump($int_fn($var)); // int(10)
try 
    $int_fn("foo");
 catch (TypeError $e) 
    echo $e->getMessage(), "\n"; // Argument 1 passed to closure() must be of the type int, string given, called in x on line y

通过 PHP 7.1,它们支持参数中的 ?type,这也允许参数为空。

$funn = fn(?int... $args): array => $args;
var_dump($funn(20, null, 30)); // Array(3)  [0]=> int(20) [1]=> NULL [2]=> int(30) 

如果你向上面的函数提供一个字符串或其他任何东西而不是 int,那么你会得到一个错误

传递给 closure() 的参数必须是 int 或 null 类型,给定字符串,在第 y 行的 x 中调用

嵌套箭头函数

$var = 6;
var_dump((fn() => fn() => $var)()());  // int(6)
var_dump((fn() => function() use($var)  return $var; )()()); // int(6)

闭包内的任何可能的错误都不会抛出除非被调用

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$b = 1;
fn() => $b + $c; // no error, nothing


ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$b = 1;
(fn() => $b + $c)(); // Notice: Undefined variable: c in the location on line x

如果错误报告已关闭,那么您只会收到int(1)如何使用 PHP。现在是 7.4?For quick online testing 只需将这些代码粘贴到那里 对于您的本机系统,我刚刚克隆了 this branch of php-src 并使用 GCC 和 make 编译它。我通过 test.php 文件和命令行进行了测试,以检查一切是否正常。

核心参考 - https://wiki.php.net/rfc/arrow_functions_v2

【讨论】:

我添加了另一个关于 IIFE Reference - What does this error mean in PHP? 的答案。如果你愿意,你可以改进它。 这也值得一提How to use $this inside php closure?【参考方案2】:

在某些情况下,箭头函数可以使您的代码更短且更具可读性。它们的设计初衷是考虑将它们用于简单的回调。以usort() 为例,它将回调函数作为用户参数。

在 PHP 7 之前,您必须执行类似的操作来为 usort() 定义自己的回调:

// old syntax prior to PHP 7
function cmp($a, $b) 
    if ($a == $b) 
        return 0;
    
    return ($a < $b) ? -1 : 1;


$a = [3, 2, 5, 6, 1];

usort($a, "cmp");

foreach ($a as $key => $value) 
    echo "$key: $value\n";

PHP 7 添加了spaceship operator,现在借助箭头函数,您可以使代码更加简洁。

// New syntax since PHP 7.4
$a = [3, 2, 5, 6, 1];

usort($a, fn($a, $b) => $a<=>$b);

foreach ($a as $key => $value) 
    echo "$key: $value\n";

在线试用3v4l.org

PHP 中的匿名函数可能非常冗长,即使它们只执行简单的操作,这也是语法较短的原因。作为另一个例子,考虑以下函数:

// Returns an array with each element squared - old syntax
function array_square($arr) 
    return array_map(function($x)  return $x*$x; , $arr);


// Returns an array with each element squared - new syntax
function array_square($arr) 
    return array_map(fn($x) => $x**2, $arr);


print_r(array_square([1,2,3,4,5]));

减少不必要的语法有助于理解代码的真正目的,但请记住,更短并不总是意味着更简洁!我建议像对待三元运算符一样谨慎对待箭头函数。仅在您知道它们有助于提高可读性时才使用它们,而不仅仅是为了使您的代码更短。

【讨论】:

以上是关于如何在 PHP 中使用箭头函数?的主要内容,如果未能解决你的问题,请参考以下文章

PHP新知:PHP 7.4 新语法:箭头函数

不能使用带有返回 void 类型提示的箭头函数

在 TypeScript 中使用箭头函数:如何使它们成为类方法?

如何在没有箭头函数的情况下重写这个 JS 方法?

如何使用箭头函数(公共类字段)作为类方法?

如何在箭头函数中添加多个参数[重复]