PHPDevs

Projekt obiektowy z Composerem i Twigiem? Czytaj!

Funkcje > Lekcja 5

Funkcje anonimowe

Nazywane są anonimowymi, gdyż nie mają swojej nazwy. Wydaje się, że funkcje takie nie są do niczego potrzebne, ale to nieprawda - czasem są przydatne. W mojej ocenie najczęściej używane są one do operacji, które nie powtarzają się w wielu miejscach i nie chcemy definiować osobnej funkcji.

Definiujemy je tak samo jak "normalne" funkcje, tyle że nie podając nazwy za słowem kluczowym function:

<?php
function () {
    // ciało funkcji anonimowej, czyli kod do wykonania
};

Co ciekawsze, funkcję anonimową możemy także przypisać do zmiennej:

<?php
$showAge = function (int $age) {
    echo 'I am ' . $age . ' years old';
};
$showAge(22);

Ciekawostka

Jak być może się domyślasz, zwykłą funkcję z nazwą też można w taki sposób wywołać - przy użyciu nazwy na przykład ze zmiennej. Nie polecałbym jednak używać takiego sposobu bez przemyślenia i wyraźnej konieczności, bo zaciemnia to kod i tak naprawdę na pierwszy rzut oka nie widać jaka to funkcja się uruchomi.

<?php
function getName() {
    return 'Marek';
};
$run = 'getName';
echo $run();

Callback

Tutaj warto poruszyć jeszcze temat tzw. callbacków zwanych wywołaniami zwrotnymi, funkcjami zwrotnymi. Jest to również funkcja, która zostaje przekazana do argumentu innej funkcji. Dzięki temu może być wywołana bezpośrednio w niej. Wiem, to brzmi trochę skomplikowanie, ale w rzeczywistości nie jest tak źle. Trochę funkcji dostępnych w PHP przyjmuje callbacki, ale możesz też przyjmować je we własnych funkcjach, nie ma problemu.

Spójrzmy teraz na praktyczny przykład. Weźmy np. funkcję array_filter(), która iteruje po każdym elemencie tablicy, uruchamia przekazany callback dla każdego i gdy zwrócone zostanie false to usuwa dany element.

<?php
$numbers = [1, 5, 10, 15];
$filtered = array_filter($numbers, function (int $number): bool {
    return $number > 8;
});
var_dump($filtered); // only 10 and 15

W tym przypadku argument $number jest automatycznie wstawianym każdym elementem tablicy po kolei. Jako callback możemy też wskazać zmienną pod którą będzie funkcja anonimowa lub podać po prostu nazwę funkcji.

Wyobraź sobie teraz jednak sytuację, że potrzebujemy jeszcze przekazać do wnętrza callbacka jakąś wartość z zewnątrz. Pewnie od razu myślisz o argumentach i super, ale niestety tutaj argumenty wstrzykiwane są "odgórnie" przez array_filter(), nie ma do nich dostępu. Dlatego też dostępna jest konstrukcja z use, dzięki której możemy tego dokonać.

<?php
$baseNumber = 4;
$numbers = [1, 5, 10, 15];
$filtered = array_filter($numbers, function (int $number) use ($baseNumber): bool {
    return $number + $baseNumber > 8;
});
var_dump($filtered); // 8 and 10 and 15

Zwróć uwagę, że jest to trochę inny mechanizm niż argumenty. Nie możemy przekazać tu jakiejś wartości i w funkcji widzieć jej pod inną nazwą. Nie możemy też określić typu. Nazwałbym to takim rozszerzeniem zasięgu zmiennej, udostępnieniem jej do wnętrza tej funkcji z zewnątrz.

Funkcje strzałkowe (arrow functions) php >=7.4

Jest to skrócony zapis funkcji, które nie mają nazw. Jeśli znasz inne języki programowania, na przykład JavaScript, to być może ten zapis nie będzie dla Ciebie niczym nowym. Ma służyć jedynie uproszczeniu i skróceniu zapisu dla małych operacji. Prezentuje się on tak:

fn(argumenty) => ciało

W ciele funkcji może być tylko jedna instrukcja, która zostanie zwrócona - nie używamy return. Wydaje się, że taki zapis jest więc nieco ograniczający, ale z drugiej strony w części przypadków będzie po prostu krótszy i czystszy. Powróćmy do naszego wcześniejszego przykładu i przeróbmy go na nowy zapis:

<?php
$numbers = [1, 5, 10, 15];
$filtered = array_filter($numbers, fn(int $number): bool => $number > 8);
var_dump($filtered); // only 10 and 15

Podobnie możemy użyć tu wartości z zewnątrz, ale już nie ma zapisu z use - po prostu wartości z zewnątrz są normalnie dostępne wewnątrz takiej funkcji.

<?php
$baseNumber = 4;
$numbers = [1, 5, 10, 15];
$filtered = array_filter($numbers, fn(int $number): bool => $number + $baseNumber > 8);
var_dump($filtered); // 8 and 10 and 15

Na razie tyle na ten temat. Myślę, że przedstawione zastosowanie jest tym, które spotkasz najczęściej. Więcej w dokumentacji.

Poprzednia lekcja Następna lekcja

Udostępnij

  • Facebook
  • Twitter

Komentarze