Il pipe operator (|>) è una delle principali novità introdotte in PHP 8.5, l'ultimo major update del noto linguaggio di sviluppo server side. Esso consente di concatenare più funzioni (o strutture richiamabili) da sinistra a destra. Il valore dell'espressione a sinistra viene passato automaticamente come primo e unico argomento al callable posizionato, invece, sulla destra.
Cos'è il pipe operator
Questa funzionalità, definita da alcuni come un vero e proprio syntactic sugar ("zucchero sintattico"), non introduce nuove capacità logiche nell'engine del progetto, elimina però la necessità di annidare continuamente le funzioni o di creare delle variabili temporanee ridondanti.
Quando scriviamo codice, l'uso dell'operatore di null coalescing (??) e del pattern ternario (? :) è abbastanza comune. Ma cosa succede se proviamo a concatenare una serie di trasformazioni tramite pipe all'interno di una condizione? In questo caso il pipe operator ha una precedenza maggiore rispetto agli operatori condizionali. Se il pipe viene posizionato sul lato sinistro di un operatore di null coalescing o di un ternario, l'intera catena di pipe viene eseguita per prima.
Nello stesso modo, gli operatori di uguaglianza hanno una precedenza inferiore rispetto al pipe operator. Questo significa che non c'è bisogno di avvolgere l'intera pipeline tra parentesi tonde per verificarne il risultato. La catena esegue tutte le sue trasformazioni e, solo alla fine, viene confrontato il valore di output.
Sintassi del pipe operator
La sintassi di base dell'operatore segue la struttura seguente:
$risultato = $valore |> callable;
Nello specifico, un callable è un tipo di dato che rappresenta qualcosa che può essere chiamato come se fosse una funzione. Non si tratta di un tipo di dato primitivo come per esempio una stringa o un intero, ma di un vincolo di tipo che comunica al linguaggio di poter accettare qualsiasi valore purché lo si possa eseguire aggiungendo delle parentesi tonde alla fine.
Il modo più comune, ed elegante, per sfruttare il nostro operatore è in combinazione con la First-Class Callable Syntax (...) che è stata introdotta in PHP 8.1. Quindi avremo:
// Prima di PHP 8.5: chiamate annidate, difficili da leggere dall'interno verso l'esterno
$slug = strtolower(str_replace(' ', '-', trim($title)));
// Con PHP 8.5: lettura naturale da sinistra a destra
$slug = $title |> trim(...) |> str_replace(' ', '-', ...) |> strtolower(...);
Cosa è possibile passare a destra del pipe?
L'operatore richiede sul lato destro qualsiasi struttura che PHP riconosca come callable valido. Si potrebbe trattare di funzioni native o personalizzate tramite First-Class Callables:
trim(...)
Ma anche di metodi di istanza o statici:
$istanza->metodo(...)
o
Classe::metodo(...)
Stesso discorso per quanto riguarda le funzioni anonime:
fn($x) => $x * 2O
Così come gli oggetti invocabili come le istanze di classi che implementano il metodo magico __invoke().
Un esempio in cui troviamo sia funzioni native che arrow function potrebbe essere il seguente:
$input = " I Love PHP 8.5! ";
$output = $input
|> trim(...)
|> (fn(string $s) => str_replace('!', '', $s))
|> strtolower(...);
// Risultato: "i love php 8.5"
Vincoli e limitazioni del pipe operator
L'implementazione del pipe operator in PHP 8.5 presenta alcune regole ferree che sono volte a evitare possibili ambiguità sintattiche. Abbiamo un solo parametro che viene richiesto, cioè il callable a destra deve accettare esattamente un solo argomento obbligatorio.
Se una funzione richiede più parametri obbligatori, l'operazione fallirà. Inoltre non avremo alcun passaggio per riferimento in quanto le funzioni che alterano le variabili originali tramite reference (come ad esempio array_pop() o sort()) genereranno un errore a livello di compilazione.
Trattandosi di un operatore di espressione a tutti gli effetti, esso può essere utilizzato ovunque sia consentita un'espressione (assegnazioni, istruzioni di return, condizioni if..).
In ogni caso, però, la precedenza associativa sarà sinistra. L'operatore si muove rigorosamente da sinistra a destra e ha una priorità che si attiva prima dei normali operatori di confronto.
Da ricordare che parliamo di un costrutto sintattico nativo inedito che non è retrocompatibile con PHP 8.4 o versioni precedenti. Se quindi provate a eseguire uno script che utilizza l'operatore |> su un server o in un ambiente containerizzato basato su una versione precedente di PHP, il motore lancerà immediatamente un errore in fase di compilazione:
Parse error: syntax error, unexpected token ">" in /path/to/script.php on line X