Funkcionalno programiranje u PHP-u

PHP podržava funkcije prve klase (first-class funkcije), što znači da funkcija može biti dodeljena promenljivoj. I korisnički definisane i ugrađene funkcije mogu biti referencirane promenljivom i pozvane dinamički. Funkcije se mogu prosleđivati kao argumenti drugim funkcijama (odlika nazvana Funkcije višeg reda) i funkcija može vraćati druge funkcije.

Rekurzija, osobina koja omogućava funkciji da poziva samu sebe, je podržana u samom jeziku, ali se većina PHP kôda fokusira na iteriranje.

Anonimne (anonymous) funkcije (sa podrškom za closures) su prisutne od verzije PHP 5.3 (2009).

PHP 5.4 je dodao mogućnost da se closure poveže sa obimom (scope) objekta, a takođe i poboljšao podršku za callable tipove, tako da se oni praktično u skoro svim slučajevima mogu koristiti na isti način kao anonimne funkcije.

Najčešći slučaj korišćenja funkcija višeg reda pri implementaciji Strategy paterna. Ugrađena array_filter() funkcija od parametara zahteva niz (podatke) i funkciju (strategiju ili callback) koja će biti korišćena kao filter nad svakim elementom prosleđenog niza.

<?php
$input = array(1, 2, 3, 4, 5, 6);

// Definisanje anonimne funkcije u promenljivu
$filter_even = function($item) {
    return ($item % 2) == 0;
};

// Ugrađena array_filter funkcija prihvata niz i callback funkciju
$output = array_filter($input, $filter_even);

// Callback funkcija ne mora da bude dodeljena nekoj promenljivoj. Ovo je takođe ispravno:
$output = array_filter($input, function($item) {
    return ($item % 2) == 0;
});

print_r($output);

Closure je anonimna funkcija koja može da pristupi promenljivama izvan svog opsega (scope) bez korišćenja globalnih promenljivih. U teoriji, closure je funkcija sa određenim argumentima koji su zatvoreni njenom definicijom. Closure funkcije mogu da prevaziđu ograničenja po pitanju opsega na dosta čist način.

U sledećem primeru je closure u vidu funkcije koja vraća jednu filter funkciju za potrebe array_filter() iz grupe filter funkcija.

<?php
/**
 * Kreira anonimnu filter funkciju koja prihvata item-e > $min.
 *
 * Vraća funkciju iz grupe "veće od n" filtera
 */
function criteria_greater_than($min)
{
    return function($item) use ($min) {
        return $item > $min;
    };
}

$input = array(1, 2, 3, 4, 5, 6);

// Poziv array_filter nad nizom i određenom filter funkcijom
$output = array_filter($input, criteria_greater_than(3));

print_r($output); // items > 3

Svaka filter funkcija iz grupe prihvata samo elemente koji su veći od određene minimalne vrednosti. Filter kojeg vraća criteria_greater_than je closure sa $min argumentom čija je vrednost zatvorena u opsegu funkcije (prosleđuje se kao argument pri pozivu criteria_greater_than funkcije).

Rano bind-ovanje se podrazumevano koristi za uvoz $min promenljive u kreiranu funkciju. Za prave closure-e sa kasnim bind-ovanje je potrebno koristiti referencu prilikom uvoza promenljive. Zamislite neku templejt biblioteku ili biblioteku za validaciju ulaznih podataka, gde se definiše closure koji zahvata promenljive u opsegu, a pristupa im se kasnije pri izvršavanju anonimne funkcije.