Funkcje anonimowe i arrow functions
🎯 Po tej lekcji napiszesz funkcję anonimową z use i arrow function oraz użyjesz ich razem z array_map.
Do tej pory tworzyłeś funkcje ze stałą nazwą. PHP pozwala też tworzyć funkcje bez nazwy — przypisywać je do zmiennych i przekazywać jako argumenty. To otwiera zupełnie nowy sposób myślenia o kodzie.
Zasięg zmiennych — ważna różnica
Zanim przejdziemy do funkcji anonimowych, poznaj kluczową zasadę PHP: funkcje mają własny zasięg zmiennych. Zmienna zdefiniowana poza funkcją nie jest widoczna w jej środku:
<?php
declare(strict_types=1);
$wiadomosc = 'Cześć!';
function wyswietl(): void
{
echo $wiadomosc; // Uwaga: Undefined variable $wiadomosc
}
wyswietl();
To celowa cecha PHP — chroni przed nieoczekiwanymi powiązaniami między zmiennymi. Jeśli chcesz skorzystać ze zmiennej zewnętrznej, musisz to zrobić jawnie.
Funkcje anonimowe (closures)
Funkcja anonimowa to funkcja bez nazwy — przechowujesz ją w zmiennej:
<?php
declare(strict_types=1);
$powitaj = function(string $imie): string {
return 'Cześć, ' . $imie . '!';
};
echo $powitaj('Ola'); // wynik: Cześć, Ola!
echo $powitaj('Kuba'); // wynik: Cześć, Kuba!
Funkcja anonimowa działa jak zmienna — możesz ją przekazać do innej funkcji jako argument.
Słowo kluczowe use — importowanie zmiennych
Żeby funkcja anonimowa mogła korzystać ze zmiennej z zewnętrznego zakresu, musisz ją zaimportować przez use:
<?php
declare(strict_types=1);
$prefix = 'Zamówienie nr ';
$formatuj = function(string $numer) use ($prefix): string {
return $prefix . $numer;
};
echo $formatuj('#001'); // wynik: Zamówienie nr #001
echo $formatuj('#002'); // wynik: Zamówienie nr #002
use ($prefix) kopiuje wartość zmiennej $prefix w momencie definicji funkcji. Późniejsza zmiana $prefix nie wpłynie na closure — chyba że przekażesz referencję przez use (&$prefix).
Arrow functions — fn
PHP 7.4 wprowadził krótszą składnię: arrow function zapis fn:
<?php
declare(strict_types=1);
$pozdrow = fn(string $imie): string => 'Hej, ' . $imie . '!';
echo $pozdrow('Anna'); // wynik: Hej, Anna!
Arrow function różni się od closure dwoma rzeczami:
- Krótszy zapis — zamiast
function(...) { return ...; }piszeszfn(...) => ... - Automatyczne przechwytywanie zakresu — nie potrzebuje
use, widzi zmienne z zewnątrz automatycznie
<?php
declare(strict_types=1);
$prefix = 'Produkt: ';
// Closure wymaga use:
$f1 = function(string $n) use ($prefix): string { return $prefix . $n; };
// Arrow function przechwytuje automatycznie:
$f2 = fn(string $n): string => $prefix . $n;
echo $f1('Jabłka'); // wynik: Produkt: Jabłka
echo $f2('Mleko'); // wynik: Produkt: Mleko
array_map czy array_filter. Closure z use sprawdza się, gdy potrzebujesz wielu linii kodu lub chcesz modyfikować zmienną zewnętrzną przez referencję.Ciało arrow function to zawsze jedno wyrażenie — nie napiszesz w nim wielu instrukcji ani nie użyjesz klamer {}. Gdy potrzebujesz więcej, użyj zwykłej funkcji anonimowej z use.
Zastosowanie z array_map
Najczęstsze zastosowanie funkcji anonimowych i arrow functions to przekazywanie ich do funkcji wyższego rzędu, takich jak array_map:
<?php
declare(strict_types=1);
$imiona = ['ola', 'kuba', 'anna'];
// Closure:
$wielkie = array_map(function(string $i): string {
return strtoupper($i);
}, $imiona);
// Arrow function — krócej:
$wielkie = array_map(fn(string $i): string => strtoupper($i), $imiona);
print_r($wielkie);
// wynik:
// Array
// (
// [0] => OLA
// [1] => KUBA
// [2] => ANNA
// )
Przykład z przechwytywaniem zmiennej z zakresu zewnętrznego:
<?php
declare(strict_types=1);
$stawkaVAT = 0.23;
$cenyNetto = [100, 200, 350];
$cenyBrutto = array_map(fn($c) => round($c * (1 + $stawkaVAT), 2), $cenyNetto);
print_r($cenyBrutto);
// wynik:
// Array
// (
// [0] => 123
// [1] => 246
// [2] => 430.5
// )
Arrow function automatycznie widzi $stawkaVAT bez use — dlatego jest tu idealnym wyborem.
use ($x) kopiuje wartość. Żeby zmiana wewnątrz closure wpłynęła na oryginał, użyj use (&$x). Arrow functions zawsze przechwytują przez wartość — nie można przez referencję.Funkcje w tej lekcji
Sprawdź się
Jak funkcja anonimowa (closure) uzyskuje dostęp do zmiennej z otaczającego zakresu?
Funkcje anonimowe w PHP nie widzą zmiennych z zewnątrz automatycznie. Trzeba je jawnie dołączyć przez use($zmienna).
Czym arrow function (fn) różni się od funkcji anonimowej pod względem zasięgu?
fn automatycznie przechwytuje zmienne z zewnętrznego zakresu przez wartość — nie musisz pisać use. To główna zaleta arrow functions.
Co zwraca array_map(fn($x) => $x * 2, [1, 2, 3])?
array_map stosuje podaną funkcję do każdego elementu tablicy i zwraca NOWĄ tablicę z wynikami. Oryginalna tablica [1, 2, 3] pozostaje niezmieniona.
Ćwiczenie
Masz tablicę imion: ['ola', 'kuba', 'anna']. Użyj array_map z arrow function, żeby zamienić każde imię na wersję z wielką pierwszą literą (użyj ucfirst). Wyświetl wynik przez print_r.
Pokaż rozwiązanie
<?php
declare(strict_types=1);
$imiona = ['ola', 'kuba', 'anna'];
$sformatowane = array_map(fn($i) => ucfirst($i), $imiona);
print_r($sformatowane);
// wynik:
// Array
// (
// [0] => Ola
// [1] => Kuba
// [2] => Anna
// )