Как использовать стрелочные функции в PHP?

Мне стало известно о стрелочные функции в PHP 7.4. Я пытался использовать их как

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

Потому что я увидел оператор => в пулреквесте. Так же, как javascript.

Я ожидал, что на выходе будет «2», но это не сработало! я получил

Parse error: syntax error, unexpected ')' in /test.php on line 3

Поэтому я изначально проголосовал за это, потому что это, очевидно, вопрос, который был задан исключительно для того, чтобы вы могли на него ответить. По-видимому, это поощряется (вики-сообщество все еще существует?), поэтому я отозвал отрицательный голос ... неохотно.

Sean Bright 18.06.2019 23:46

Этот вопрос (и ответ на него) был очень полезен для меня. Я не знал, что в 7.4 есть функции стрелок.

zedfoxus 18.06.2019 23:48

@SeanBright большое спасибо, и да, я думаю, это поощряется stackoverflow.blog/2011/07/01/…

weegee 18.06.2019 23:48

конечно, это должен быть вопрос по теме в первую очередь? и это путь к широкому.

user10051234 18.06.2019 23:48
В RFC есть масса полезной информации., который связан непосредственно с PR, который вы связали.
Sean Bright 18.06.2019 23:49

Да, я только что протестировал их все и упомянул об этом здесь, поэтому, если люди хотят спросить об областях, ключевых словах или чем-то еще в этом отношении, они могут обратиться сюда @SeanBright.

weegee 18.06.2019 23:50

Я думаю, что это нужно было добавить в Справочник — что означает этот символ в PHP? вместо нового вопроса и ответа.

John Conde 19.06.2019 00:08

@JohnConde Это была первая мысль, которая пришла мне в голову, но она создаст некоторую путаницу, поскольку у нас есть много ответов, касающихся символа стрелки stackoverflow.com/questions/1241819stackoverflow.com/questions/1655336stackoverflow.com/questions/4758791 Итак, я подумал, что для этого нужны новые вопросы и ответы.

weegee 19.06.2019 00:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
12
8
9 056
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Стрелочные функции в PHP представлены в PHP 7.4. Это немного отличается.

ключевое слово фн

Новое ключевое слово fnтеперь зарезервированное ключевое слово.

Раньше мы продолжали использовать ключевое слово 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 для вышеуказанной функции, вы получите сообщение об ошибке

Argument passed to {closure}() must be of the type int or null, string given, called in x on line y

Вложенные стрелочные функции

$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 сейчас?
Для быстрого онлайн-тестирования просто вставьте туда этот код

Для вашей родной системы я просто клонировал эта ветка php-src и скомпилировал его с помощью GCC и make. Я провел тестирование с помощью файла test.php и командной строки, чтобы проверить, все ли работает.

Основная ссылка — https://wiki.php.net/rfc/arrow_functions_v2

Я добавил еще один ответ о IIFE Ссылка. Что означает эта ошибка в PHP?. Вы можете улучшить его, если хотите.

Dharman 19.06.2019 01:05

Также стоило бы упомянуть Как использовать $this внутри закрытия php?

Dharman 19.06.2019 01:09

В некоторых ситуациях стрелочные функции могут сделать ваш код короче и читабельнее. В первую очередь они были разработаны с мыслью об использовании их для простых обратных вызовов. В качестве примера рассмотрим 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 добавлен оператор космического корабля, и теперь благодаря стрелочным функциям вы можете сделать свой код намного чище.

// 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]));

Сокращение ненужного синтаксиса помогает понять реальную цель кода, но имейте в виду, что короче не всегда значит чище! Я бы рекомендовал относиться к стрелочным функциям с той же осторожностью, что и к тернарным операторам. Используйте их только тогда, когда вы знаете, что это улучшает читабельность, а не только для того, чтобы сделать ваш код короче.

Другие вопросы по теме