L'ultima versione di PHP semplifica molto l'utilizzo degli Heredoc e dei Nowdoc. Prima di vedere le novità, però, diamo una veloce introduzione a cosa sono questi ultimi.
Heredoc e Nowdoc in PHP <= 7.2
Heredoc
La sintassi Heredoc ci consente di aggiungere delle stringhe di grandi dimensioni e/o multilinea senza bisogno di effettuare escaping o concatenazione di caratteri.
Invece di avere una situazione del tipo:
$name = 'Simone';
$html = '<ul>';
$html .= '<li>' . $name . '</li>';
$html .= '<li>elemento 1</li>';
$html .= '<li>elemento 2</li>';
$html .= '<li>elemento 3</li>';
$html = '</ul>';
echo $html;
Possiamo usare Heredoc
in questo modo:
$name = 'Simone';
$html = <<<HTML
<ul>
<li>$name</li>
<li>elemento 1</li>
<li>elemento 2</li>
<li>elemento 3</li>
</ul>
HTML;
echo $html;
In entrambi i casi, l'istruzione echo $html
restituirà lo stesso risultato. La differenza è nella leggibilità e la manutenibilità del codice. L'output per entrambi sarà:
<ul>
<li>Simone</li>
<li>elemento 1</li>
<li>elemento 2</li>
<li>elemento 3</li>
</ul>
Per usare un Heredoc
, quindi, è necessario definire un marker (nel nostro caso HTML
) con cui iniziare e terminare la stringa. All'inizio della stringa il marker è anticipato da <<<
mentre al termine della stringa è terminato con un punto e virgola.
Nowdoc
Il Nowdoc è del tutto simile ad Heredoc con due differenze sostanziali: il marker è racchiuso tra apici in fase di definizione e non viene eseguito il parsing delle variabili. L'esempio di prima, quindi, utilizzando il Nowdoc non sostituirà la variabile $name
ma la utilizzerà come stringa. Vediamo un esempio:
$name = 'Simone';
$html = <<<'HTML'
<ul>
<li>$name</li>
<li>elemento 1</li>
<li>elemento 2</li>
<li>elemento 3</li>
</ul>
HTML;
echo $html;
L'output sarà il seguente:
<ul>
<li>$name</li>
<li>elemento 1</li>
<li>elemento 2</li>
<li>elemento 3</li>
</ul>
Sia per Heredoc che per Nowdoc, fino alla versione 7.2 di PHP, era necessario chiudere la stringa con marker;
all'inizio di una nuova stringa, senza alcun tipo di indentazione. Pena la ricezione di un syntax error
.
Un utilizzo come il seguente, quindi, avrebbe sollevato un syntax error
:
class foo {
public $bar = <<<EOT
my string
EOT;
}
//Parse error: syntax error, unexpected end of file in ... on line xx
Heredoc e Nowdoc in PHP 7.3
Fortunatamente la limitazione vista nell'esempio precedente è stata risolta con l'ultima versione di PHP. Facendo girare lo stesso codice stavolta avremo un output senza errori:
class foo {
public $bar = <<<EOT
my string
EOT;
}
$foo = new foo();
echo $foo->bar;
//l'output sarà:
//
//my string
Può sembrare una differenza minima ad un primo sguardo, ma entrando un po' più in dettaglio nella modifica ci rendiamo conto che, oltre ad un vantaggio a livello di codice leggibile, abbiamo altri vantaggi nelle indentazioni.
Usiamo qualche esempio per chiarire meglio di cosa si sta parlando.
class foo {
public $bar = <<<EOT
first line
second line
third line
EOT;
}
$foo = new foo();
echo $foo->bar;
//l'output sarà:
//
// first line
// second line
//third line
In sostanza dalla versione 7.3 viene considerata la posizione del marker di chiusura come inizio dell'indentazione delle stringhe. Proprio per questa ragione non è possibile chiudere un costrutto più a destra delle stringhe che lo compongono. Anche qui vediamo un esempio per chiarire:
class foo {
public $bar = <<<EOT
first line
second line
third line
EOT;
}
$foo = new foo();
echo $foo->bar;
//l'output sarà:
//
//Parse error: Invalid body indentation level (expecting an indentation level of at least 9) in ... on line xx
Se guardiamo con attenzione nel codice la chiusura del marker è più a destra rispetto alla sua linea precedente. Questo ha generato un errore in PHP.
Utilizzi pratici
Una volta approvata la RFC (Request for Comments) su Heredoc e Nowdoc vediamo anche cosa cambia nell'utilizzo quotidiano con un paio di esempi pratici.
PHP 7.2
stringManipulator(<<<END
a
b
c
END
);
$values = [<<<END
a
b
c
END
, 'd e f'];
PHP 7.3
stringManipulator(<<<END
a
b
c
END);
$values = [<<<END
a
b
c
END, 'd e f'];
Anche in questo caso ad un primo sguardo sembrano modifiche non importanti ma la leggibilità del codice è migliorata tantissimo.