如何在PHP中使用箭头功能?

wee*_*gee 4 php arrow-functions php-7.4

我了解PHP 7.4中的箭头功能。我尝试像这样使用它们

<?php
$num = 1;
$arrowfunction = () => {
   return $num + 1;
}
echo $arrowfunction();
Run Code Online (Sandbox Code Playgroud)

因为我=>在拉取请求中看到了运算符。就像JavaScript。

我希望输出为“ 2”,但这没有用!我有

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

wee*_*gee 11

PHP 7.4中引入了PHP中的箭头功能。他们有些不同

fn关键字

现在,新fn关键字是保留关键字

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

$add = function ($valone,$valtwo) {
    return $valone + $valtwo;
};
$add(1,2) // 3
Run Code Online (Sandbox Code Playgroud)

随着新箭头功能的出现:

$add = function ($valone,$valtwo) {
    return $valone + $valtwo;
};
$add(1,2) // 3
Run Code Online (Sandbox Code Playgroud)

父范围

此前,我们必须遵循与关键字的使用use变量的介入从父范围。

$y = 1;
$fn = function ($x) use ($y) {
    return $x + $y;
};
echo $fn(2); // 3
Run Code Online (Sandbox Code Playgroud)

父范围中定义的表达式将按值隐式捕获。

$y = 1;
$fn = fn($x) => $x + $y;
echo $fn(2); // 3
Run Code Online (Sandbox Code Playgroud)

上面是关于$this变量内部类方法的。

class foo {
   public function test() {
       $context = fn() => var_dump($this);
       $context(); 
   }
}
$test = new foo();
$test->test();  // object(foo)#1 (0) { }
Run Code Online (Sandbox Code Playgroud)

就像以前一样,我们过去通过使用use关键字从父作用域中获取变量来执行操作,因此这意味着我们无法将函数中变量的值写入上层作用域。

$y = 1;
$fn = fn() => $y++;
$fn(); // Has no effect
echo $y  // 1
Run Code Online (Sandbox Code Playgroud)

如果我们正在考虑从闭包中分配另一个变量的值,那么这也将不起作用

$y = 1;
$f = 0;
$fn = fn() => $f = $y + 1;
$fn();
echo $f; // 0
Run Code Online (Sandbox Code Playgroud)

功能签名

这在PHP中是全新的,这使我们可以定义函数的类型,变量以及函数返回的值

fn(int $x) => $x; // the argument type must be (int)
fn(): int => $x; // type of return value (int)
Run Code Online (Sandbox Code Playgroud)

调用函数时,如果未将定义的参数类型放在参数中,则会引发错误。可以通过使用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
}
Run Code Online (Sandbox Code Playgroud)

在PHP 7.1中,它们支持?typein参数,该参数也允许参数为null。

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

如果您向上述函数提供字符串或其他内容而不是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)
Run Code Online (Sandbox Code Playgroud)

除非调用,否则不会抛出闭包内部的任何可能的错误

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
Run Code Online (Sandbox Code Playgroud)

如果关闭了错误报告功能,那么您将获得int(1)

如何使用PHP。7.4现在?
为了进行快速的在线测试,只需将这些代码粘贴在那里。

对于您的本机系统,我刚刚克隆了php-src的这个分支,并使用GCC和make对其进行了编译。我通过test.php文件和命令行进行了测试,以检查是否一切正常。

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


Dha*_*man 7

箭头功能可以使您的代码在某些情况下更短,更易读。设计它们的主要目的是考虑将它们用于简单的回调。例如,考虑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";
}
Run Code Online (Sandbox Code Playgroud)

PHP 7添加了一个太空飞船操作符,现在借助箭头功能,您可以使代码更简洁。

// 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";
}
Run Code Online (Sandbox Code Playgroud)

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]));
Run Code Online (Sandbox Code Playgroud)

减少不必要的语法有助于理解代码的真正目的,但请记住,缩短并不总是意味着更干净!我建议对箭头函数的处理与三元运算符相同。仅当您知道它们有助于提高可读性时才使用它们,而不仅仅是使您的代码更短。