Le raccomandazioni raccolte in questo manuale aiutano i programmatori a scrivere codice PHP elegante, aumentandone nel contempo manutenibilità e qualità generale.
Le raccomandazioni presenti in questo manuale sono orientate principalmente sullo stile di redazione del codice e sono annotate in modo da comprenderne il contesto d’uso.
Le raccomandazioni sono raggruppate per “elemento” e seguono questo schema:
Raccomandazione
// example $example = 'example';
Motivazione, conseguenze ed informazioni aggiuntive.
La sezione “Motivazione, conseguenze ed informazioni aggiuntive” aiuta a comprendere il contesto per l’uso della raccomandazione evitando che si avviino “guerre di religione” come di solito accade in tema di standard e linee guida di codifica.
Si è scelto di usare solo raccomandazioni “obbligatorie” per ridurre al minimo il rischio di avere più stili di codifica per singoli elementi di codice.
Questo Manuale di Stile è pensato per essere utilizzato con la versione 7 e successive di PHP, ben potendo le raccomandazioni essere facilmente adattate per una versione precendente di PHP.
indice
- Raccomandazione generale
- Directory
- File
- Istruzioni
- Commenti
- Tipi
- Variabili
- Costanti
- Operatori
- Strutture di controllo
- Funzioni
- Namespace
- Interfacce
- Trait
- Classi
- Costanti di classe
- Proprietà
- Metodi
- Note legali
Raccomandazione generale
Qualsiasi raccomandazione del manuale deve essere violata se migliora la leggibilità.
L’obiettivo principale delle raccomandazioni è migliorare la leggibilità e di conseguenza la comprensione, la manutenibilità e la qualità generale del codice. Poichè è impossibile coprire tutti i casi specifici, il programmatore deve essere flessibile.
Directory
I nomi delle directory devono contenere solo caratteri alfanumerici ed essere scritti in CapitalizedWords
.
I numeri sono consentiti nei nomi delle directory, ma sono da evitarsi nella maggior parte dei casi.
Questa raccomandazione nasce dal fatto che i nomi delle directory vengono mappati con i nomi dei namespace, creando un collegamento biunivoco con questi ultimi e rendendo predicibile la posizione di un namespace.
Nota sulla terminologia: la notazione “CapitalizedWords” si ha quando un nome è composto da più parole unite e la prima lettera di ogni parola è in maiuscolo.
File
I nomi dei file devono contenere solo caratteri alfanumerici, essere scritti in CapitalizedWords
e terminare con l’estensione .php
.
I numeri sono consentiti nei nomi dei file, ma sono da evitarsi nella maggior parte dei casi.
Questa raccomandazionie nasce dal fatto che i nomi dei file vengono mappati con i nomi delle interfacce, dei trait o delle classi, creando un collegamento biunivoco con questi ultimi e rendendo predicibile la posizione delle interfacce, dei trait, delle classi, delle librerie o dei file template.
Nei file deve essere utilizzata esclusivamente la codifica dei caratteri UTF-8 senza BOM (Byte Order Mark).
La codifica può essere dichiarata usando
declare(encoding = 'utf-8');
nella parte superiore del file.
A differenza di UTF-16 e UTF-32, non esiste un ordine di byte da indicare in un file con codifica UTF-8 e il BOM (Byte Order Mark) può avere un effetto collaterale negativo nell’invio dell’output, impedendo all’applicazione di impostare le proprie intestazioni.
Le righe dei file devono avere una lunghezza massima di 72 caratteri e terminare con un singolo carattere di avanzamento riga Unix LF (linefeed).
Un limite di 72 caratteri rende necessario distribuire la logica o le espressioni complesse in funzioni e/o metodi, nonché assegnare nomi più brevi e più espressivi a funzioni e classi.
Limitando la larghezza delle righe a 72 caratteri si migliora la leggibilità del codice.
Limitando la larghezza della finestra dell’editor a 72 caratteri, è possibile avere diversi file aperti fianco a fianco e funziona bene quando si utilizzano gli strumenti di revisione del codice che presentano le due versioni nelle colonne adiacenti.
Il wrapping predefinito nella maggior parte degli strumenti interrompe la struttura visiva del codice, rendendolo più difficile da capire. Il limite è stato scelto per evitare il wrapping degli editor con la larghezza della finestra impostata su 80 caratteri, anche se lo strumento posiziona un glifo marcatore nella colonna finale quando effettua il wrapping delle linee. Alcuni strumenti basati sul Web potrebbero non offrire affatto il ritorno a capo automatico della linea.
Non aggiungere spazi finali alla fine delle righe, ma terminare le righe secondo la convenzione dei file di testo Unix. I caratteri di avanzamento riga sono rappresentati come numero ordinale 10 oppure come numero esadecimale 0x0A. Questo è più un problema per gli sviluppatori che lavorano in ambiente Windows, ma in ogni caso assicurarsi che l’editor di testo sia configurato per salvare i file con interruzioni di riga Unix.
Nota sulla terminologia: il line-wrapping avviene quando il codice che potrebbe occupare in altro modo regolarmente una singola riga è diviso in più righe.
L’incompletezza di una riga, perchè divisa a causa della sua eccessiva lunghezza, deve essere resa evidente.
$sum = $a + $b + $c +
$d + $e;
$obj->method($param1, $param2,
$param3);
setText('Long line split' .
'into two parts.');
for ($tableNo = 0; $tableNo < $nTables;
$tableNo += $tableStep)
{
// code
}
Le righe vanno divise quando un’istruzione supera il limite di 72 caratteri indicato sopra.
È difficile dare regole rigide su come le righe dovrebbero essere divise, ma gli esempi sopra dovrebbero dare un suggerimento generale.
In generale:
- dividi la riga dopo una virgola;
- dividi dopo un operatore;
- allinea la nuova riga con l’inizio dell’espressione sulla riga precedente;
I caratteri speciali come TAB e interruzione di pagina devono essere evitati.
Questi caratteri sono destinati a causare problemi a editor, stampanti, emulatori di terminali o debugger quando vengono utilizzati in un ambiente multi-programmatore e/o multipiattaforma.
I file devono usare un’indentazione di quattro spazi.
Ciò aiuta ad evitare problemi con diff, patch, cronologia e annotazioni. L’uso degli spazi rende anche facile inserire una sub-indentazione a grana fine per l’allineamento tra le righe.
Gli spazi non devono mai essere mescolati con la tabulazione.
L’indentazione è usata per enfatizzare la struttura logica del codice. L’indentazione di uno spazio è troppo piccola per raggiungere questo risultato. L’indentazione maggiore di quattro spazi rende il codice profondamente annidato e difficile da leggere, aumentando peraltro la possibilità che le righe debbano essere divise.
Tutti i file sorgente devono appartenere ad un namespace
specifico.
L’assegnazione di ogni file ad un
namespace
specifico piuttosto che alnamespace
globale, è una conseguenza dell’applicazione delle tecniche di programmazione orientate agli oggetti del linguaggio PHP.
I file sorgente devono essere aperti dal tag PHP esteso <?php
seguito da una riga vuota.
<?php
// blank line
$a = 'foo'; // code php
$b = 'bar'; // code php
// blank line
Devono sempre essere usati esclusivamente i tag PHP estesi
<?php ?>
e mai quelli concisi<? ?>
. Questo è il modo più portabile per includere codice PHP su diversi sistemi operativi e configurazioni.
Nei file che contengono esclusivamente codice PHP, il tag di apertura
<?php
deve essere seguito da una singola riga vuota al fine di migliorare la leggibilità del codice.
Il tag di chiusura deve essere omesso nei file sorgente.
Nei file che contengono esclusivamente codice PHP, il tag di chiusura
?>
deve essere sostituito da una singola riga vuota.
Il tag di chiusura PHP
?>
in un documento PHP é facoltativo per il parser PHP. Tuttavia, se utilizzato, qualsiasi spazio vuoto successivo al tag di chiusura, introdotto dallo sviluppatore, dall’utente o da un’applicazione FTP, può causare output indesiderati, errori PHP o, se questi ultimi vengono soppressi, pagine vuote. Per questo motivo, tutti i file che contengono esclusivamente codice PHP devono omettere il tag di chiusura?>
e terminare con una singola riga vuota
I file sorgente che dichiarino interfacce, trait, classi o librerie di funzioni devono contenere solo le dichiarazioni di interfaccia, trait, classe o funzioni.
L’inserimento di codice aggiuntivo che provochi effetti collaterali deve essere evitato, per migliorare la leggibilità, la manutenibilità e la comprensione del codice.
I file template devono distinguere tra indentazione PHP e HTML.
<div>
<?php foreach ($arr as $key => $value) : ?>
<p><?php echo $value; ?></p>
<?php endforeach; ?>
</div>
Ciò rende molto più facile trovare tag di apertura e chiusura corrispondenti, definiti con diversi rientri.
Nei file template deve essere PHP in HTML piuttosto che HTML in PHP.
// bad
if ($isSubmitted)
{
echo '<span class="isSubmitted">' . $isSubmitted . '</span>';
}
// good
<?php if ($isSubmitted) : ?>
<span class="isSubmitted"><?php echo $isSubmitted; ?></span>
<?php endif; ?>
Dopotutto, PHP è un linguaggio di scripting incorporato in HTML, e non il contrario.
Nei file template devono essere usati i tags estesi <?php ?>
.
<div>
<?php foreach ($arr as $key => $value) : ?>
<p><?php echo $value; ?></p>
<?php endforeach; ?>
</div>
L’uso del tag echo esteso
<?php echo
era richiesto nel caso in cui un server non avesse avuto la direttiva INIshort_open_tag
abilitata. Oggi questa esigenza risulta superata dopo chePHP 5.4
ha reso sempre disponibile l’uso del tag echo conciso<?=
indipendentemente dalla direttiva INIshort_open_tag
. Tuttavia per ragioni di consistenza e leggibilità non deve mai essere usato il tag echo conciso<?=
preferendogli l’uso esclusivo del tag esteso<?php echo
.
Il punto e virgola finale non deve mai essere omesso, neanche quando PHP lo permette, come nell’esempio che segue:
<div> <?php foreach ($arr as $key => $value) : ?> <p><?php echo $value ?></p> // bad <?php endforeach; ?> </div>
Istruzioni
Tutto il codice deve utilizzare le funzionalità avanzate di PHP 7 per la programmazione orientata agli oggetti.
Ciò significa che non dovrebbero esserci funzioni al di fuori delle classi, se non assolutamente necessario. Se è necessario un “contenitore” per alcune funzioni di supporto, prendere in considerazione la creazione di una classe statica o di un trait.
Ciò significa anche che deve essere abilitata la modalità
strict type
per la dichiarazione di tipo (si veda l’istruzionedeclare
), in modo da rendere il codice auto-documentante, oltre che più sicuro.
La tipizzazione rigorosa ha un effetto non solo sulle dichiarazioni del tipo dei parametri, ma anche sulle dichiarazioni del tipo restituito. Nella modalità predefinita, i valori restituiti verranno convertiti nel tipo corretto se non sono già di quel tipo. In modalità
strict type
, il valore restituito deve essere del tipo corretto, altrimenti verrà generato un erroreTypeError
.
Specificando un tipo, il debugging diventa più semplice in quanto il passaggio di un tipo errato restituirà un messaggio di errore più utile. Si ricordi di NON usare una classe come tipo nel suggerimento del tipo, ma solo ed esclusivamente un’interfaccia. Ciò consente ad altri sviluppatori di fornire le proprie implementazioni, se necessario, senza modificare il codice esistente.
L’error reporting deve essere impostato con la costante E_ALL
.
error_reporting(E_ALL);
Consente di suggerire le modifiche al codice che garantiscano la migliore interoperabilità e compatibilità all’indietro del codice.
Il livello di error reporting richiesto è
E_STRICT
, pertanto se viene utilizzata una versione precedente alla5.4
l’error_reporting deve essere deve essere impostato come segue:error_reporting(E_STRICT);
A partire dalla versione
5.4
la costanteE_ALL
includeE_STRICT
;
La lingua utilizzata per i nomi deve essere l’inglese.
L’inglese è la lingua preferita per lo sviluppo a livello internazionale.
Le abbreviazioni e gli acronimi devono avere tutte lettere in minuscolo eccetto la prima se usati come nome.
L’utilizzo di sole maiuscole per questo tipo di denominazioni causerà conflitti con le altre raccomandazioni di denominazione. Una variabile denominata
PDFFile
) la leggibilità viene seriamente ridotta, perchè la parola che segue l’acronimo non spicca come dovrebbe.
Tutte le parole chiave in PHP devono essere in minuscolo.
Questa raccomandazione non si applica a
TRUE
,FALSE
eNULL
che sono in realtà costanti.
Le istruzioni devono essere tutte su una propria riga.
$foo = 'this';
$bar = 'that';
$bat = str_replace($foo, $bar, $bag);
Evitare di combinare più istruzioni su una stessa riga come negli esempi seguenti:
// bad $foo = 'this'; $bar = 'that'; $bat = str_replace($foo, $bar, $bag); // bad $foo = substr(strtoupper('test'), 0, 1); // good $foo = 'test'; $foo = strtoupper($foo); $foo = substr($foo, 0, 1);
I valori NON vanno allineati, neanche quando ciò appare appropriato, come nell’esempio seguente:
$var = ''; $other_var = '';
L’allineamento può facilitare la leggibilità, ma crea problemi per la manutenzione futura. Si consideri un cambiamento futuro che deve toccare solo una riga. Questo cambiamento spinge il programmatore a regolare lo spazio bianco anche sulle linee vicine, probabilmente attivando una serie di riformattazioni a cascata. Ciò può, nel peggiore dei casi, causare inutili attività lavorative, ma nel migliore dei casi corrompe ancora le informazioni sulla cronologia delle versioni, rallenta i revisori ed esacerba i conflitti di fusione.
Per l’indentazione deve essere utilizzato lo stile Allman.
function foo($bar)
{
// code
}
Le parentesi graffe vanno sempre posizionate su una nuova riga e indentate allo stesso livello dell’istruzione che le possiede, mentre le istruzioni nel blocco hanno un livello maggiore di indentazione.
Il codice così indentato, è chiaramente separato dall’istruzione che lo possiede.
Le unità logiche all’interno di un blocco di codice devono essere separate da una riga vuota.
if ($condition1)
{
// code
}
if ($condition2)
{
// code
}
if ($condition3)
{
// code
}
Introducendo una riga vuota tra le unità logiche correlate, si migliora la leggibilità del codice. Le righe di codice correlate devono essere raggruppate in blocchi, separati gli uni dagli altri per mantenere il più alto grado di leggibilità possibile. La definizione di correlate dipende dal codice. Si noti la poca leggibilità del codice seguente:
if ($condition1) { // code } if ($condition2) { // code } if ($condition3) { // code }
Commenti
Il codice ingannevole deve essere riscritto, non commentato.
In generale, l’uso dei commenti dovrebbe essere minimizzato, rendendo il codice autodocumentante mediante scelte appropriate di denominazione e una struttura logica esplicita.
Tutti i commenti devono essere scritti in inglese.
A livello internazione l’inglese è la lingua preferita per codificare.
L’identificatore di commenti //
deve essere seguito da uno spazio.
// This is a comment
Migliora la leggibilità facendo risaltare il testo.
I commenti devono utilizzare esclusivamente l’identificatore //
, inclusi i commenti su più righe.
// Comment spanning
// more than one line.
L’uso dell’identificatore
//
per i commenti garantisce che sia sempre possibile commentare intere sezioni di un file usando/* */
per scopi di debug.
I commenti devono essere preceduti da una riga vuota a meno che il commento non sia all’inizio di una struttura di codice.
while (TRUE)
{
// Do something
doSomething();
}
Si noti l’assenza della riga vuota prima del commento.
I commenti devono precedere il codice cui si riferiscono.
Come corollario, i commenti non devono essere sulla stessa riga del codice a cui si riferiscono, come nell’esempio che segue:
$var = ''; // bad comment
I commenti su più righe devono essere seguiti da una riga vuota quando sono molto grandi.
// Comment single line
$foo = 'bar';
// Comment long
// Comment too long
// Comment very long
// Comment very very long
// Comment really too long
$baz = $object->foo($bar);
Migliora la leggibilità del codice. E del commento.
Le nuove righe dovrebbero sempre iniziare con una lettera maiuscola a meno che la linea non sia la continuazione di una frase oppure il termine sia codice case sensitive.
I commenti devono essere indentati allo stesso livello del codice cui si riferiscono.
while (TRUE)
{
// Do something
doSomething();
}
La raccomandazione tende ad evitare che i commenti interrompano la struttura logica del programma.
Tipi
I numeri a virgola mobile devono sempre essere scritti con il punto decimale ed almeno un decimale.
$total = 0.0;
$epsilon = 3.0e8;
$sum = 2.0 * 10.0;
La raccomandazione tende ad enfatizzare la diversa natura dei numeri interi ed in virgola mobile. Matematicamente sono due concetti completamente diversi e non compatibili.
I numeri a virgola mobile devono sempre essere scritti con una cifra prima del punto decimale.
$total = 0.7;
Il numero ed il sistema di espressione in PHP è preso in prestito dalla matematica e si dovrebbe aderire alle convenzioni matematiche per la sintassi laddove possibile.
Inoltre, 0.7 è molto più leggibile di .7 e non c’è modo che possa essere confuso con l’intero 7. Si veda l’esempio seguente:
// bad $total = .7;
Le stringhe letterali devono essere delimitate dalle virgolette singole.
$string = 'example string';
Le stringhe che contengono virgolette singole devono essere delimitate dalle virgolette doppie.
$str = "That's a 'magic' sock.";
Questa sintassi è preferibile rispetto al carattere di escape
\
poiché è molto più facile da leggere. Inoltre è particolarmente utile per le istruzioni SQL:$sql = "SELECT `id`, `name` " . "FROM `people` " . "WHERE `name`='Mickey' OR `name`='Minnie'";
Le stringhe devono essere scritte senza variabili da sostituire.
$string = 'Hello ' . $name . ', welcome back!';
Questa sintassi migliora le leggibilità del codice rispetto ai seguenti esempi:
// bad $string = "Hello $name, welcome back!"; // bad $string = "Hello {$name}, welcome back!"; // bad $string = "Hello ${name}, welcome back!";
La riga deve essere divisa dopo l’operatore di concatenazione quando l’istruzione supera il limite di 72 caratteri, allineando la nuova riga con l’inizio dell’espressione sulla riga precedente.
$sql = "SELECT `id`, `name` " .
"FROM `people` " .
"WHERE `name`='Mickey' OR `name`='Minnie'" .
"ORDER BY `name` ASC ";
Quando si concatenano le stringhe con l’operatore
.
, è meglio suddividere l’istruzione in più righe per migliorarne la leggibilità. In questi casi, ogni riga successiva deve essere riempita con tanti spazi bianchi, tali da allinearla con la riga precedente.
Gli array devono essere dichiarati con la sintassi concisa.
$arr = [];
Array con molti dati devono essere dichiarati in questo modo:
$foo = [ 'bar' => 'abc', 'baz' => 123, 'foo' => TRUE, 'foox' => [ 'mickey' => [], 'mouse' => 123.456, ], ];
Gli array devono avere indici numerici positivi.
L’uso di numeri negativi come indici di un array può causare problemi con alcune funzioni della libreria standard di PHP.
I delimitatori degli elementi ,
di un array devono essere seguiti da uno spazio.
$arr = ['Mickey', 'Minnie', 1, 2, 3];
Migliora la leggibilità del codice.
Gli operatori di assegnazione di un valore a una chiave, =>
, devono essere preceduti e seguiti da uno spazio.
$arr = ['firstKey' => 'firstValue', 'secondKey' => 'secondValue'];
Migliora la leggibilità del codice.
Gli array suddivisi su più righe devono avere il seguente formato:
$arr = [
'firstKey' => 'firstValue',
'secondKey' => 'secondValue',
];
$arr = [
5, 4, 18,
2, 65, $var,
'Mickey', 'Mouse',
];
Riepilogando:
- il primo elemento deve essere posizionato sulla riga successiva a quella della dichiarazione dell’array;
- ogni elemento deve essere su una propria riga;
- gli elementi devono avere un’indentazione maggiore rispetto alla riga di dichiarazione dell’array;
- gli operatori di assegnazione di un valore a una chiave
=>
devono essere allineati;- l’ultimo elemento deve essere sempre delimitato da una virgola;
- la parentesi di chiusura deve essere su una propria riga allo stesso livello di indentazione della riga contenente la dichiarazione dell’array;
L’uso della virgola finale dopo l’ultimo elemento nell’array riduce al minimo la possibilità che si verifichino errori di analisi a causa di una virgola mancante per l’aggiunta di nuovi elementi.
Variabili
I nomi delle variabili devono contenere solo caratteri alfanumerici ed essere scritti in mixedCase
.
$firstName = 'Mickey';
I numeri sono consentiti nei nomi delle variabili, ma sono da evitarsi nella maggior parte dei casi.
I nomi delle variabili dovrebbero essere quanto più descrittivi possibile, ma anche quanto più brevi è possibile, quel tanto che basti a descrivere i dati che lo sviluppatore intende memorizzare in essi.
I nomi di variabili di una sola lettera, come
$i
e$k
, sono da evitarsi, tranne che nei cicli più piccoli. Se un ciclo contiene più di 20 righe di codice, le variabili dell’indice dovrebbero avere nomi più descrittivi.
Le variabili nell’ambito globale sono da evitarsi. Se sono proprio necessarie, si utilizzino le proprietà di classe
static
o le costanti anziché le variabili globali.
Le variabili generiche devono avere lo stesso nome del loro tipo.
$person = new \Person();
Riduce la complessità riducendo il numero di termini e nomi utilizzati. Inoltre rende facile dedurre il tipo dato dal nome della variabile.
Se per qualche motivo questa convenzione non sembra adattarsi, c’è un forte sospetto che il nome del tipo è scelto male.
Le variabili non generiche hanno un ruolo. Queste variabili possono spesso essere nominate combinando il ruolo e il tipo:
function sendMessage(\Person $fromPerson, \Person $toPerson) : mixed { }
Le variabili devono avere un significato univoco.
Migliora la leggibilità, assicurando che tutti i concetti siano rappresentati in modo univoco. Riduce inoltre la possibilità di errore da effetti collaterali.
Le variabili devono essere mantenute in vita per il minor tempo possibile.
Mantenendo le operazioni su una variabile all’interno di un piccolo ambito, è più facile controllare gli effetti collaterali, e non, della variabile.
Costanti
I nomi delle costanti devono contenere solo caratteri alfanumerici, essere tutte in maiuscolo con le parole separate da caratteri di sottolineatura.
define('DATABASE_HOST', 'dbhost');
define('DATABASE_NAME', 'dbname');
define('DATABASE_USER', 'dbuser');
define('DATABASE_PASSWORD', 'dbpwd');
Le costanti devono essere denominate in modo da indicare il loro scopo e contenuto.
Anche le costanti PHP predefinite come
TRUE
,FALSE
eNULL
devono essere tutte in maiuscolo.
I numeri sono consentiti nei nomi delle costanti, ma sono da evitarsi nella maggior parte dei casi.
I nomi delle costanti dovrebbero essere quanto più descrittivi possibile, ma anche quanto più brevi è possibile.
La definizione di costanti nell’ambito globale con la funzione
define
è consentita, ma fortemente sconsigliata. Sono da preferirsi le costanti di classe, seguite dalle costanti definite all’interno di unnamespace
e, solo se proprio sono necessarie, le costanti nell’ambito globale. Si noti che è meglio inserire le costanti globali nel punto di ingresso dello script o meglio ancora in un file separato da includere nel punto di ingresso dello script.
I nomi delle costanti che rappresentano un concetto comune devono avere un prefisso comune.
define('COLOR_RED', '#ff0000');
define('COLOR_GREEN', '00ff00');
define('COLOR_BLUE', '0000ff');
Ciò indica che le costanti appartengono allo stesso insieme, e quale concetto rappresentino.
Un’alternativa a questo approccio consiste nel mettere le costanti all’interno di un’interfaccia in modo da utilizzare il nome dell’interfaccia come prefisso:
interface Color { const RED = '#ff0000'; const GREEN = '#00ff00'; const BLUE = '#0000ff'; }
L’istruzione const
deve essere preferita all’istruzione define
nella dichiarazione di una costante.
const COLOR_RED = '#ff0000';
const COLOR_GREEN = '#00ff00';
const COLOR_BLUE = '#0000ff';
Si noti che
const
non funziona con le espressioni PHP, pertanto nel caso in cui debba essere definita una costante in maniera condizionale o con un valore non letterale va utilizzata l’istruzionedefine
:if ( ! defined('MAINTENANCE_MODE')) { define('MAINTENANCE_MODE', 'development'); }
Operatori
Gli operatori binari devono essere circondati da uno spazio.
if ($a == $b)
{
// code
}
Migliora la leggibilità del codice.
Gli operatori unari devono essere uniti alla variabile cui afferiscono, fatta eccezione per !
.
@fopen('file/path');
Migliora la leggibilità del codice.
L’operatore
!
segue la raccomandazione degli operatori binari e quindi deve essere diviso dalla variabile cui afferisce da uno spazio, per migliorare la leggibilità del codice, soprattuto quando si trova nelle espressioni condizionali come nel caso che segue:if ( ! $condition) { // code }
Gli operatori unari di incremento
++
e decremento--
vanno posizionati prima della variabile piuttosto che successivamente, per ragioni di efficienza.
Quando si confrontano una variabile con un’espressione o una costante, queste ultime devono essere sempre poste a sinistra.
if (TRUE == $foo)
{
// code
}
Questa raccomandazione evita un’assegnazione accidentale all’interno dell’istruzione condizionale.
Quando si eseguono confronti logici che coinvolgono variabili, le variabili vanno messe a destra, mentre costanti, letterali o chiamate di funzione sul lato sinistro. Se nessuna delle due parti è una variabile, l’ordine non è importante.
Se nell’esempio precedente viene omesso un segno di uguale, si avrà un errore di analisi, perché non è possibile assegnare qualcosa ad a una costante come TRUE. Si veda, a contrario l’esempio seguente:
if ($foo = TRUE) { // code }
l’assegnazione è perfettamente valida, generando un bug nel codice.
Questo modo di scrivere le condizioni è anche detto Yoda condition.
L’operatore di concatenazione deve essere preceduto e seguito da un singolo spazio.
$string = 'Mickey' . ' ' . 'Mouse';
Migliora la leggibilità del codice.
L’operatore ternario deve essere contenuto su una sola riga.
$variable = isset($options['variable']) ? $options['variable'] : TRUE;
Opzionalmente le parentesi possono essere utilizzate attorno al controllo delle condizioni dell’operatore ternario per maggiore chiarezza. Ternari più lunghi dovrebbero essere suddivisi in altre dichiarazioni.
Gli operatori ternari non dovrebbero mai essere annidati, come nell’esempio seguente:
// Nested ternaries are bad $variable = isset($options['variable']) ? isset($options['othervar']) ? TRUE : FALSE : FALSE;
Si noti la scarsa leggibilità dell’espressione precedente.
L’operatore ternario deve essere diviso se supera la lunghezza massima della riga.
$b = $condition3 && $condition4 ?
$foo_man_this_is_too_long_what_should_i_do :
$bar;
Deriva dalla raccomandazione sulla divisione delle righe.
L’operator @
deve essere evitato assolutamente.
L’uso dell’operatore
@
per silenziare i messaggi di errore rende il debug più difficile, oltre a rallentare l’esecuzione del codice.
Gli operatori di confronto rigorosi devono essere preferiti a tutti gli altri.
if ($foo === $bar)
{
// code
}
if ($foo !== $baz)
{
// code
}
Gli operatori di confronto rigorosi vanno preferiti ogni volta che è possibile, per evitare problemi con valori booleani che potrebbero portare ad un comportamento diverso da quello che ci si aspetta, come nei seguenti casi:
// bad, avoid truthy comparisons if ($foo == $bar) { // code } // bad, avoid falsy comparisons if ($foo != $baz) { // code }
Strutture di controllo
Tra la parola chiave di una struttura di controllo e la parentesi aperta deve esserci uno spazio.
// single space following PHP control structures, but not in interior parenthesis
foreach ($arr as $key => $value)
{
// code
}
Questo è fatto per distinguere le parole chiave di una struttura di controllo dai nomi di funzioni.
Le strutture di controllo devono essere indentate secondo lo stile Allman.
if ($condition)
{
}
else
{
}
Si noti come entrambe le parole chiave iniziano una nuova riga e le parentesi di apertura e chiusura vengono posizionate su una nuova riga.
Deriva dalla raccomandazione generale sull’indentazione.
Le parentesi tonde devono essere prive di spazi aggiuntivi al loro interno.
// no space inside the brackets
if ($condition)
{
}
Il corpo di una struttura di controllo deve essere sempre racchiuso tra parentesi graffe indipendentemente dal numero di istruzioni.
if ($condition)
{
// code block
}
Questo standardizza l’aspetto delle strutture e riduce la probabilità che il codice si interrompi se viene aggiunta un’istruzione dimenticandosi delle parentesi, sebbene il codice non dovrebbe mai essere scritto per adattarsi ai cambiamenti che potrebbero insorgere.
break
L’uso di break
nei cicli deve essere evitata.
Questa istruzione dovrebbe essere utilizzata solo se dimostra di essere più leggibile rispetto alle controparti strutturate.
L’istruzione break
deve essere indentata allo stesso livello del codice presente all’interno del blocco di codice cui appartiene.
foreach ($iterable as $key => $value)
{
echo $key . ' => ' . $value;
if ('foo' === $value)
{
break;
}
}
All’interno di una struttura switch
l’istruzione break
deve essere preceduta e seguita da una riga vuota.
switch ($value)
{
case ($condition) :
$a = 'foo';
$b = 'bar';
// blank line
break;
// blank line
case ($condition) :
$a = 'bar';
$b = 'foo';
// blank line
break;
// blank line
default :
$a = 'no-foo';
$b = 'no-bar';
// blank line
break;
// blank line
}
Migliora la leggibilità del codice.
continue
L’uso di continue
nei cicli deve essere evitata.
Questa istruzione dovrebbe essere utilizzata solo se dimostra di essere più leggibile rispetto alle controparti strutturate.
declare
Il costrutto declare
deve essere la prima istruzione nel codice PHP.
<?php // blank space
// blank line
declare(encoding = 'utf-8');
declare(strict_types = 1);
// blank line
Utilizzando il costrutto
declare
a livello globale, tutto il codice che segue sarà interessato da tale istruzione ed evita dimenticanze.
Il costrutto
php declare(encoding = 'utf-8')
consente di evitare effetti collaterali negativi dovuti ad altre codifiche di caratteri.
Il costrutto
php declare(strict_types = 1)
consente di rendere il codice autodocumentante, oltre a renderlo più sicuro.
do-while
L’uso della struttura di controllo do-while
deve essere evitata.
$i = 0;
do
{
echo ++$i;
}
while ($i < 10)
La struttura di controllo
do-while
è meno leggibile di unwhile
ordinario o di un ciclofor
, perché l’istruzione condizionale si trova nella parte inferiore del ciclo. Il lettore deve eseguire la scansione dell’intero ciclo per comprendere lo scopo del ciclo.
Inoltre, i cicli
do-while
non sono necessari. Qualsiasi ciclodo-while
può essere facilmente riscritto con un ciclowhile
o con un ciclofor
. Ridurre il numero di costrutti utilizzati migliora la leggibilità.
Il blocco di codice di una struttura di controllo do-while
deve seguire l’indentazione di Allman.
do
{
// code
}
while ($condition)
Deriva dalla raccomandazione generale sull’indentazione.
for
Solo le istruzioni di controllo del ciclo devono essere incluse nell’istruzione for()
.
$sum = 0;
for ($i = 0; $i < 10; ++$i)
{
$sum += $value[$i];
}
Aumenta la manutenibilità e la leggibilità, creando una chiara distinzione tra istruzioni di controllo e istruzioni contenute nel ciclo.
Il blocco di codice di una struttura di controllo for
deve seguire l’indentazione di Allman.
for ($i = 0; $i < 10; ++$i)
{
// code
}
Deriva dalla raccomandazione generale sull’indentazione.
Nei file template, dove PHP è mescolato all’Html, deve essere utilizzata la sintassi alternativa per la struttura di controllo for
.
<div>
<?php for ($i = 0; $i < 10; ++$i) : ?>
<p>true condition</p>
<?php endfor; ?>
</div>
La sintassi alternativa migliora la leggibilità all’interno del codice Html.
Si notino gli spazi che circondano i due punti
:
per evidenziare questi ultimi.
foreach
Il blocco di codice di una struttura di controllo foreach
deve seguire l’indentazione di Allman.
foreach ($iterable as $key => $value)
{
echo $key . ' => ' . $value;
}
Deriva dalla raccomandazione generale sull’indentazione.
Nei file dove PHP è mescolato all’Html deve essere utilizzata la sintassi alternativa per la struttura di controllo foreach
.
<div>
<?php foreach ($arr as $key => $value) : ?>
<p><?php echo $value; ?></p>
<?php endforeach; ?>
</div>
La sintassi alternativa migliora la leggibilità all’interno del codice Html.
Si notino gli spazi che circondano i due punti
:
per evidenziare questi ultimi.
goto
L’istruzione goto
deve essere evitata assolutamente.
Rende il codice difficile da correggere oltre che difficile da comprendere.
if-else
Le espressioni condizionali complesse devono essere evitate, introducendo semmai variabili booleane temporanee.
$isFinished = ($elementNo < 0) || ($elementNo > $maxElement);
$isRepeatedEntry = $elementNo === $lastElement;
if ($isFinished || $isRepeatedEntry)
{
// code
}
Assegnando le espressioni booleane a delle variabili, lo script si auto-documenta. Sarà più facile eseguire il debug oltre che leggere e manutenere lo script.
L’istruzione condizionale deve essere su una riga separata.
$isFinished = ($elementNo < 0) || ($elementNo > $maxElement);
if ($isFinished)
{
doExecute();
}
Questa raccomandazione è per aiutare il debug. Quando si scrive su una singola riga, non è chiaro se il test sia realmente vero o meno.
// bad if ($isFinished) doExecute();
Se l’espressione condizionale supera il limite massimo della riga (72 caratteri), la riga va divisa dopo un operatore logico, allineando la nuova riga con l’inizio dell’espressione sulla riga precedente e con la parentesi di chiusura che deve essere sulla stessa riga dell’ultima condizione.
if ($test1 && $test2 || $test3) { // code }
Deriva dalla raccomandazione sulla divisione delle righe.
Le dichiarazioni eseguibili devono essere evitate nelle istruzioni condizionali.
$file = fopen($local_file, "r");
if ( ! $file)
{
// code
}
Le condizioni con istruzioni eseguibili sono semplicemente molto difficili da leggere. Questo è particolarmente vero per i programmatori nuovi in PHP. Si veda l’esempio seguente:
if ( ! ($file = fopen($local_file, "r"))) { // code }
Il blocco di codice di una struttura di controllo if-else
deve seguire l’indentazione di Allman.
if ($condition)
{
// code block
}
if ($condition)
{
// code block
}
else
{
// code block
}
if ($condition)
{
// code block
}
elseif ($condition)
{
// code block
}
else
{
// code block
}
L’approccio scelto è considerato migliore perchè rende più semplice la manipolazione dell’istruzione, ad esempio quando si spostano altre clausole.
L’uso di
else
doporeturn
va evitato dove ciò ha senso, preferendo le condizioni di guardia, come nel caso seguente:// no good if ($condition) { // code block return true; } else { // code block } // good if ($condition) { // code block return true; } // code block
Si veda anche la raccomandazione per
return
.
L’istruzione elseif
deve essere sempre preferita a else if
.
L’istruzione
else if
non è compatibile con la sintassi alternativa dell’istruzioneif else
, pertanto, per consistenza col resto del codice, va utilizzata solo l’istruzioneelseif
.
Nei file dove PHP è mescolato all’Html deve essere utilizzata la sintassi alternativa per la struttura di controllo if-else
.
<div>
<?php if ($alpha) : ?>
<p>true alpha condition</p>
<?php elseif ($beta) : ?>
<p>true beta condition</p>
<?php else : ?>
<p>default condition</p>
<?php endif; ?>
</div>
La sintassi alternativa migliora la leggibilità all’interno del codice Html.
Si notino gli spazi che circondano i due punti
:
per evidenziare questi ultimi.
require / require_once / include / include_once
Per includere un file incondizionatamente deve essere utilizzata l’istruzione require_once
.
L’istruzione va utilizzata nei casi in cui si vuol includere un file sempre e comunque, tipicamente all’inizio di uno script. Un file incluso con
require_once
non sarà incluso di nuovo dainclude_once
.
Per includere un file condizionatamente deve essere utilizzata l’istruzione include_once
.
Laddove l’inclusione di un file sia soggetta a qualche condizione (ad esempio, metodi factory), va usato
include_once
. L’uso direquire_once
einclude_once
assicurerà che i file vengano inclusi solo una volta. Condividono la stessa lista di file, quindi non bisogna preoccuparsi di mescolarli.
Le istruzioni di inclusione devono essere utilizzate senza parentesi.
require_once ROOT_PATH . '/dir/file.php';
Le istruzioni di inclusione
require_once
einclude_once
sono istruzioni del linguaggio e non funzioni, pertanto la corretta formattazione è senza parentesi.
Le classi devono essere incluse attraverso la funzione autoload
oppure una soluzione personalizzata.
$object = new \Namespace\ClassName();
Ciò consente ai pacchetti di funzionare senza modifiche, indipendentemente dal modo in cui sono strutturati su disco, incluso l’esecuzione di un singolo file di grandi dimensioni, all’interno di un archivio
phar
e fornisce la necessaria flessibilità.
Le classi dovrebbero essere semplicemente utilizzate con il
namespace
completo in modo da documentarne la posizione all’interno delle cartelle.
return
L’istruzione return
deve essere separata da un gruppo di istruzioni da una riga vuota.
function bar() : int
{
$sum = 0;
for ($i = 0; $i < 11; ++$i)
{
$sum += $i;
}
// blank line
return $sum;
}
Questa raccomandazione migliora la leggibilità del codice.
La raccomandazione non si applica nel caso in cui
return
sia l’unica istruzione all’interno di un blocco di istruzioni, come nell’esempio seguente:if ( ! $condition) { return NULL; }
Quando una funzione o un metodo restituiscono valori nulli esplicitamente si deve utilizzare return NULL;
.
function foo() : null
{
// code
return NULL;
}
Migliora la leggibilità del codice, oltre ad auto-documentarlo.
Si noti il modo differente di scrivere il tipo
null
dalla costanteNULL
.
Quando una funzione o un metodo restituiscono valori void
si deve utilizzare return;
.
public function setFirstName(string $firstName) : void
{
$this->firstName = $firstName;
return;
}
Migliora la leggibilità del codice, oltre ad auto-documentarlo.
Il valore restituito da return
deve essere privo di parentesi.
function bar() : string
{
// code
return $bar;
}
Racchiudere il valore restituito da
return
tra parentesi può ostacolare la leggibilità, in aggiunta alla rottura del codice se una funzione o un metodo vengono successivamente modificati per restituire un valore per riferimento.function bar() : string { // code return ($bar); // bad }
L’istruzione return
deve essere inserita il prima possibile, nel caso di condizioni semplici.
function foo($bar, $baz)
{
if ( ! $condition)
{
return NULL;
}
//assume
//that
//here
//is
//the
//whole
//logic
//of
//this
//method
return $value;
}
Per mantenere la leggibilità delle funzioni e dei metodi, è consigliabile inserire
return
il prima possibile, se si applicano condizioni semplici che possono essere verificate all’inizio di un metodo. Molto meno leggibile il codice nell’esempio seguente:function foo($bar, $baz) { if ($condition) { //assume //that //here //is //the //whole //logic //of //this //method return $value; } else { return NULL; } }
switch
Il blocco di codice di una struttura di controllo switch
deve seguire l’indentazione di Allman.
switch ($value)
{
case ($condition) :
$a = 'foo';
$b = 'bar';
// blank line
break;
// blank line
case ($condition) :
$a = 'bar';
$b = 'foo';
// blank line
break;
// blank line
default :
$a = 'no-foo';
$b = 'no-bar';
// blank line
break;
}
Deriva dalla raccomandazione generale sull’indentazione.
Nei file dove PHP è mescolato all’Html deve essere evitato l’uso della sintassi alternativa per la struttura di controllo switch
.
Poiché qualsiasi output (inclusi spazi bianchi) tra un’istruzione
switch
e il primocase
genererà un errore di sintassi, per poter utilizzare la sintassi alternativa diswitch
deve essere eliminata l’indentazione della prima istruzionecase
rendendo oscuro il codice.
try-catch
Il blocco di codice di una struttura di controllo try-catch
deve seguire l’indentazione di Allman.
try
{
// code block
}
catch (\Exception $exception)
{
// code
}
try
{
// code block
}
catch (\Exception $exception)
{
// code
}
finally
{
// code block
}
Deriva dalla raccomandazione generale sull’indentazione.
while
Le variabili di loop devono essere inizializzate immediatamente prima del ciclo.
$i = 0;
while ($i < 10)
{
echo ++$i;
}
Migliora la leggibilità del codice.
Il blocco di codice di una struttura di controllo while
deve seguire l’indentazione di Allman.
while ($i < 10)
{
// code
}
Deriva dalla raccomandazione generale sull’indentazione.
Nei file dove PHP è mescolato all’Html deve essere utilizzata la sintassi alternativa per la struttura di controllo while
.
<div>
<?php while ($condition) : ?>
<p>true condition</p>
<?php endwhile; ?>
</div>
La sintassi alternativa migliora la leggibilità all’interno del codice Html.
Si notino gli spazi che circondano i due punti
:
per evidenziare questi ultimi.
Funzioni
I nomi delle funzioni devono contenere solo caratteri alfanumerici, essere scritte in mixedCase
in caso di più parole ed iniziare con un verbo.
function getFirstName() : string
{
}
La verbosità è generalmente incoraggiata. I nomi delle funzioni dovrebbero essere prolissi quanto è pratico per descrivere pienamente il loro scopo e comportamento.
I numeri sono consentiti nei nomi delle funzioni, ma sono da evitarsi nella maggior parte dei casi.
Le funzioni user defined nel namespace globale sono da evitarsi nella maggior parte dei casi.
Nota sulla terminologia: la notazione “mixedCase” si ha quando un nome è composto da più parole unite e la prima lettera di ogni parola è in maiuscolo eccetto la prima lettera della prima parola.
Le funzioni devono essere sempre dichiarate in un namespace
.
Migliora l’organizzazione del codice, oltre che la portabilità dello stesso.
Le funzioni devono essere scritte secondo il seguente formato:
function getFirstName() : string
{
// code
}
Deriva dalla raccomandazione generale sull’indentazione.
Le definizioni delle funzioni iniziano su una nuova riga senza spazi tra il nome della funzione e la parentesi di apertura. Inoltre, le parentesi graffe di apertura e chiusura vengono posizionate su nuove linee. Una riga vuota deve precedere le linee che specificano il valore restituito.
L’elenco di argomenti di una funzione deve essere interrotta dopo una virgola, allineando gli argomenti, se la lunghezza massima della riga viene superata
function setName(string $title, string $firstName, string $lastName) : void { // code }
Le funzioni devono essere chiamate senza spazio tra il nome della funzione e la parentesi iniziale.
$var = getFoo($bar, $bar2, $bar3);
Tra i parametri di una funzione c’è uno spazio, come detta la raccomandazione generale.
Le funzioni dovrebbero essere chiamate senza spazi tra il nome della funzione e la parentesi di apertura e nessuno spazio tra questa e il primo parametro; uno spazio dopo la virgola tra ciascun parametro (se presente) e nessuno spazio tra l’ultimo parametro e la parentesi di chiusura. Ci dovrebbe essere spazio prima e esattamente uno spazio dopo il segno di uguale. L’allineamento su più righe è da evitarsi, come nell’esempio seguete:
// Multiple aligned function calls is bad. $short = bar('short'); $medium = bar('medium'); $long = bar('long');
L’allineamento può facilitare la leggibilità, ma crea problemi per la manutenzione futura. Si consideri un cambiamento futuro che deve toccare solo una riga. Questo cambiamento spinge il programmatore a regolare lo spazio bianco anche sulle linee vicine, probabilmente attivando una serie di riformattazioni a cascata.
Le closure devono essere scritte secondo il seguente formato:
$doExecute = function () : mixed
{
// code
};
$doOtherExecute = function () use ($arg) : mixed
{
// code
};
Deriva dalla raccomandazione generale sull’indentazione.
Si noti che il costrutto
use
è preceduto e seguito da uno spazio.
Le closure all’interno di chiamate di funzioni devono stare su una propria riga, come nell’esempio seguente:
$rowIds = array_map( function ($row) { return $row->id; }, $rows );
Ricomprendere tutti i possibili casi di indentazione è difficile, in generale si usino le seguenti linee guida:
- la parentesi di apertura di una chiamata di funzione su più linee deve essere l’ultimo contenuto della riga;
- è consentito un solo argomento per riga in una chiamata di funzione su più righe;
- gli argomenti devono essere indentati di un livello rispetto alla riga dove è chiamata la funzione;
- la parentesi di chiusura di una chiamata di funzione su più righe deve essere su una riga da sola;
$matches = array_intersect_key( $this->listeners, array_flip( preg_grep($pattern, array_keys($this->listeners), 0) ) );
Gli argomenti con valori predefiniti devono essere posti alla fine dell’elenco degli argomenti.
$var = foo($bar, $baz = 'string', $quux = NULL);
Namespace
I nomi dei namespace devono contenere solo caratteri alfanumerici ed essere scritti in CapitalizedWords
.
I numeri sono consentiti nei nomi dei namespace, ma sono da evitarsi nella maggior parte dei casi.
Queste raccomandazioni nascono dal fatto che i nomi dei namespace vengono mappati con i nomi delle directory, creando un collegamento biunivoco con queste ultime.
Migliora l’organizzazione del codice, oltre a rendere prevedibile la posizione del
namespace
all’interno delle directory.
La dichiarazione dei namespace non inizia mai con un backslash
Vendor\Space\Space
.
Ci deve essere una riga vuota prima e dopo la dichiarazione di un namespace
.
migliora la leggibilità del codice.
La definizione del namespace deve essere la prima dichiarazione del file di dichiarazione di un’interfaccia, un trait, una classe o una libreria di funzioni.
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection
{
// code
}
L’unico costrutto di codice consentito prima di una dichiarazione dello spazio dei nomi é l’istruzione
declare
per definire la codifica di un file sorgente. Inoltre, nessun codice non-PHP può precedere una dichiarazione dello spazio dei nomi, inclusi spazi extra:<html> <?php namespace MyProject; // fatal error - namespace must be the first statement in the script ?>
L’importazione di altri namespace
deve essere effettuata utilizzando l’istruzione use
.
<?php
namespace MyProject;
use \OtherNamespace;
Migliora la leggibilità del codice, oltre a renderlo portabile.
Se l’importazione di
namespace
crea conflitti tra i nomi, si può usare la parola chiaveas
per creare degli alias. In questo caso l’alias deve essere creato componendo i nomi dei sub-namespace, come nell’esempio che segue:use Baz\Qux\Quux as BazQuxQuux;
Sempre per migliorare la leggibilità del codice, va utilizzata una sola dichiarazione
use
per riga ed una sola per ogni spazio dei nomi importato.
Ci deve essere una riga vuota dopo un blocco di dichiarazioni
use
.
Le dichiarazioni
use
devono essere raggruppate perpackage
. Si vedano i seguenti esempi:// bad use Foo\Bar, Baz\Mickey, Foo\Bas; // bad use Foo\Bar; use Baz\Mickey; use Foo\Bas; // good use Foo\Bar; use Foo\Bas; use Baz\Minnie; use Baz\Mickey\Mouse; // blank line // code
Interfacce
I nomi delle interfacce devono contenere solo caratteri alfanumerici ed essere scritti in CapitalizedWords
.
I numeri sono consentiti nei nomi delle interfacce, ma sono da evitarsi nella maggior parte dei casi.
Queste raccomandazioni nascono dal fatto che i nomi delle interfacce vengono mappati con i nomi dei file, creando un collegamento biunivoco con questi ultimi.
Le interfacce devono essere dichiarati in singoli file con il nome del file corrispondente al nome della interfaccia con l’aggiunta dell’estensione .php
.
Migliora l’organizzazione del codice, oltre a rendere prevedibile la posizione dell’interfaccia all’interno delle directory.
Il corpo di un’interfaccia deve seguire l’indentazione di Allman.
interface Person
{
// code
}
Deriva dalla raccomandazione generale sull’indentazione.
La posizione di ciascun elemento all’interno dell’interfaccia deve essere prevedibile.
interface Person
{
public function getFirstName() : string;
public function getLastName() : string;
}
La raccomandazione tenta di ridurre la complessità, rendendo prevedibile la posizione di ciascun elemento dell’interfaccia.
In generale i metodi vanno ordinati alfabeticamente per nome, ma si veda anche la raccomandazione per ordinare i metodi in base ai modificatori.
Trait
I nomi dei trait devono contenere solo caratteri alfanumerici ed essere scritti in CapitalizedWords
.
I numeri sono consentiti nei nomi dei trait, ma sono da evitarsi nella maggior parte dei casi.
Queste raccomandazioni nascono dal fatto che i nomi dei trait vengono mappati con i nomi dei file, creando un collegamento biunivoco con questi ultimi.
I trait devono essere dichiarati in singoli file con il nome del file corrispondente al nome del trait con l’aggiunta dell’estensione .php
.
Migliora l’organizzazione del codice, oltre a rendere prevedibile la posizione del trait all’interno delle directory.
Il corpo di un trait
deve seguire l’indentazione di Allman.
trait Employee
{
// code
}
Deriva dalla raccomandazione generale sull’indentazione.
Classi
I nomi delle classi devono contenere solo caratteri alfanumerici ed essere scritti in CapitalizedWords
.
I numeri sono consentiti nei nomi delle classi, ma sono da evitarsi nella maggior parte dei casi.
Queste raccomandazioni nascono dal fatto che i nomi delle classi vengono mappati con i nomi dei file, creando un collegamento biunivoco con questi ultimi e rendendo predicibile la posizione di un file.
Le classi devono essere dichiarati in singoli file con il nome del file corrispondente al nome della classe con l’aggiunta dell’estensione .php
.
Migliora l’organizzazione del codice, oltre a rendere prevedibile la posizione del file sorgente della classe all’interno delle directory.
Le classi devono essere sempre dichiarate in un namespace
.
Migliora l’organizzazione del codice, oltre che la portabilità dello stesso.
Le classi devono essere dichiarate ognuna in un proprio file sorgente.
Migliora l’organizzazione del codice, oltre al fatto che i file sorgenti vanno mappati alle classi.
Il corpo di una classe deve seguire l’indentazione di Allman.
class Person extends People implements Employee
{
// all contents of class
}
Deriva dalla raccomandazione generale sull’indentazione.
Le definizioni di classe iniziano su una nuova riga e le parentesi graffe di apertura e chiusura vanno posizionate su nuove righe.
La posizione di ciascun elemento all’interno della classe deve essere prevedibile.
abstract class Person
{
const FEMALE_TITLE = 'Mrs.';
const MALE_TITLE = 'Mr.';
private $firstName;
private $lastName;
private static $gender;
abstract public function getFormalName() : string;
public function __construct(string $firstName, string $lastName, string $gender)
{
$self::gender = $gender;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() : string
{
return $this->firstName;
}
public function getLastName() : string
{
return $this->lastName;
}
protected function getTitle() : string
{
if ('female' === $self::gender)
{
return self::FEMALE_TITLE;
}
return self::MALE_TITLE;
}
}
La raccomandazione tenta di ridurre la complessità, rendendo prevedibile la posizione di ciascun elemento della classe. Gli elementi della classe vanno raggruppati e, all’interno di ciascun gruppo, ordinati alfabeticamente per nome:
- trait;
- costanti;
- proprietà;
- metodi; si vedano anche le raccomandazioni per ordinare proprietà e metodi in base ai modificatori.
Per migliorare la leggibilità il gruppo delle costanti ed il gruppo delle proprietà terminano con una riga vuota. I metodi sono seguiti da tre righe vuote eccetto l’ultimo metodo della classe dove sarebbe superfluo.
I metodi devono essere separati da tre righe vuote.
Separando i metodi con uno spazio più grande di quello utilizzato all’interno degli stessi, i metodi si distingueranno meglio all’interno della classe.
Le classi che estendono altre classi o che implementano interfacce devono dichiarare le loro dipendenze sulla stessa riga quando possibile.
class Person extends People implements Employee
{
// all contents of class
// must be indented four spaces
}
Migliora la leggibilità.
Nel caso in cui la dichiarazione delle dipendenze di classe comportino il superamento della lunghezza massima della riga, la dihiarazione va interrotta prima delle parole chiave
extends
e / oimplements
applicando un livello di rientro.class Person extends People implements Employee { // all contents of class // must be indented four spaces }
Se la classe implementa più interfacce e la dichiarazione supera la lunghezza massima della riga, la dichiarazione va interrotta dopo ogni virgola che separi le interfacce i cui nomi vanno rientrati in modo tale che si allineino.
class Person extends People implements Employee, Manager { // all contents of class // must be indented four spaces }
Le classi devono essere istanziate utilizzando sempre le parentesi, indipendentemente dal numero di argomenti del costruttore.
// bad
$person = new Person;
// good
$person = new Person();
Migliora la leggibilità del codice, oltre a renderlo consistente.
Costanti di classe
I nomi delle costanti di classe devono contenere solo caratteri alfanumerici, essere tutte in maiuscolo con le parole separate da caratteri di sottolineatura.
class Foo
{
const DATABASE_HOST = 'dbhost';
const DATABASE_NAME = 'dbname';
const DATABASE_USER = 'dbuser';
const DATABASE_PASSWORD = ''dbpwd'';
}
Le costanti devono essere denominate in modo da indicare il loro scopo e contenuto.
I numeri sono consentiti nei nomi delle costanti, ma sono da evitarsi nella maggior parte dei casi.
I nomi delle costanti dovrebbero essere quanto più descrittivi possibile, ma anche quanto più brevi è possibile.
Proprietà
I nomi delle proprietà devono contenere solo caratteri alfanumerici ed essere scritti in mixedCase
.
class Person
{
private $firstName = 'Mickey';
private $lastName = 'Mouse';
}
I numeri sono consentiti nei nomi delle proprietà, ma sono da evitarsi nella maggior parte dei casi.
I nomi delle proprietà dovrebbero essere quanto più descrittivi possibile, ma anche quanto più brevi è possibile, quel tanto che basti a descrivere i dati che lo sviluppatore intende memorizzare in essi.
Le proprietà che fanno riferimento ad oggetti dovrebbero in qualche modo essere associate alla classe di cui la proprietà è un oggetto.
class Manager { private $person; public function __construct(\Person $person) { $this->person = $person; } }
Le proprietà di classe devono essere dichiarate private
o protected
.
Il concetto di information hiding e incapsulamento è violato dalle proprietà dichiarate
public
. Devono essere invece utilizzate solo proprietà dichiarateprivate
oprotected
e metodi di accesso a queste proprietà.
Il costrutto
var
non deve essere mai utilizzato.
Le proprietà della classe vanno raggruppate in base alla visibilità e, all’interno di ciascun gruppo, ordinate alfabeticamente per nome:
- protected;
- private; la raccomandazione tenta di ridurre la complessità, rendendo prevedibile la posizione di ciascun elemento della classe.
Per una migliorare le leggibilità, non dovrebbero esserci righe vuote tra le dichiarazioni di proprietà e due righe vuote tra le sezioni di dichiarazione di proprietà e di metodo. È necessario aggiungere una riga vuota tra i diversi gruppi di visibilità.
La dichiarazione delle proprietà deve seguire il seguente pattern: (protected
|private
)[static
]property_name.
abstract class Person
{
const FEMALE_TITLE = 'Mrs.';
const MALE_TITLE = 'Mr.';
private $firstName;
private $lastName;
private static $gender;
abstract public function getFormalName() : string;
public function __construct(string $firstName, string $lastName, string $gender)
{
$self::gender = $gender;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() : string
{
return $this->firstName;
}
public function getLastName() : string
{
return $this->lastName;
}
protected function getTitle() : string
{
if ('female' === $self::gender)
{
return self::FEMALE_TITLE;
}
return self::MALE_TITLE;
}
}
La raccomandazione tenta di ridurre la complessità, rendendo prevedibile la posizione di ciascun elemento della dichiarazione di proprietà.
La lezione più importante qui è rendere obbligatorio il modificatore di visibilità. Tra i possibili modificatori, questo è di gran lunga il più importante e deve sempre esser presente nella dichiarazione di una proprietà. Per gli altri modificatori, l’ordine è meno importante, ma ha senso avere una convenzione fissa.
L’ordine di dichiarazione di proprietà in una classe si basa sulla loro visibilità: da
protected
aprivate
.
Metodi
I nomi dei metodi di una classe devono contenere solo caratteri alfanumerici, essere scritte in mixedCase
in caso di più parole ed iniziare con un verbo.
public function getFirstName() : string
{
}
I numeri sono consentiti nei nomi dei metodi, ma sono da evitarsi nella maggior parte dei casi.
La verbosità è generalmente incoraggiata. I nomi dei metodi dovrebbero essere prolissi quanto è pratico per descrivere pienamente il loro scopo e comportamento.
Questa raccomandazione segue la prassi comune nella comunità di sviluppo PHP. Anche se la raccomandazione è in pratica identica a quella sui nomi delle funzioni, i metodi in PHP sono già distinguibili dalle funzioni per la loro forma specifica quando vengono invocati:
$person->getFirstName(); getFirstName($person);
I nomi dei metodi di una classe non devono contenere il nome della propria classe.
$person->getFirstName();
Come mostrato nell’esempio, si rivela superfluo nell’uso:
// bad $person->getPersonFirstName();
Il nome del metodo deve essere immediatamente seguito dalla parentesi tonda di apertura.
class Person extends People implements Employee
{
public function setFirstName(string $firstName) : void
{
// code
}
}
Il corpo di un metodo deve seguire l’indentazione di Allman.
class Person extends People implements Employee
{
public function getFirstName() : string
{
// code
}
}
Deriva dalla raccomandazione generale sull’indentazione
La dichiarazione dei metodi deve seguire il seguente pattern: [abstract
|final
](public
|protected
|private
)[static
]method_name.
abstract class Person
{
const FEMALE_TITLE = 'Mrs.';
const MALE_TITLE = 'Mr.';
private $firstName;
private $lastName;
private static $gender;
abstract public function getFormalName() : string;
public function __construct(string $firstName, string $lastName, string $gender)
{
$self::gender = $gender;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() : string
{
return $this->firstName;
}
public function getLastName() : string
{
return $this->lastName;
}
protected function getTitle() : string
{
if ('female' === $self::gender)
{
return self::FEMALE_TITLE;
}
return self::MALE_TITLE;
}
}
La raccomandazione tenta di ridurre la complessità, rendendo prevedibile la posizione di ciascun elemento della dichiarazione di metodo.
I metodi magici precedono all’interno dei singoli gruppi gli altri metodi ordinati alfabeticamente per nome.
La lezione più importante qui è rendere obbligatorio il modificatore di visibilità. Tra i possibili modificatori, questo è di gran lunga il più importante e deve sempre esser presente nella dichiarazione del metodo. Per gli altri modificatori, l’ordine è meno importante, ma ha senso avere una convenzione fissa.
Gli argomenti dei metodi devono avere lo stesso nome del loro tipo.
public function connect(\PDO $pdo) : mixed
{
}
Riduce la complessità riducendo il numero di termini e nomi utilizzati. Inoltre rende facile dedurre il tipo dato dal nome della variabile.
Se per qualche motivo questa convenzione non sembra adattarsi, c’è un forte sospetto che il nome del tipo è scelto male.
Gli argomenti non generici hanno un ruolo. Questi argomenti possono spesso essere denominati combinando il ruolo e il tipo:
public function sendMessage(\Person $fromPerson, \Person $toPerson) : mixed { }
L’elenco di argomenti di un metodo deve essere interrotta dopo una virgola, allineando gli argomenti, se la lunghezza massima della riga viene superata.
class Foo
{
public function bar($arg1, $arg2, $arg3,
$arg4, $arg5, $arg6) : mixed
{
// code
}
}
Un numero di argomenti superiore a tre è un forte indizio di codice che può essere migliorato.
Note legali
“Manuale di Stile per PHP”. Copyright © 2018 - 2019 Guglielmo Pepe. Distribuito con licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.
Se riproduci, distribuisci o modifichi questo manuale devi fornire un’adeguata attribuzione in base alla licenza.
Se riproduci o distribuisci il manuale senza apportare sostanziali modifiche al suo contenuto, utilizza la seguente riga di attribuzione:
“Manuale di Stile per PHP”. Copyright © 2018 - 2019 Guglielmo Pepe. Distribuito con licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale. Usato in conformità alla licenza.
Se modifichi il contenuto del manuale, ad esempio per conformarlo alle convenzioni di codifica del tuo team, utilizza questa riga di attribuzione:
Adattato in conformità alla licenza a partire dal “Manuale di Stile per PHP”. Copyright © 2018 - 2019 Guglielmo Pepe. Distribuito con licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.
In ogni caso devi includere un collegamento ipertestuale o altro riferimento, collegando “Manuale di Stile per PHP” all’url https://guglielmopepe.github.io/Manuale-di-Stile-per-PHP e “Guglielmo Pepe” all’url https://www.guglielmopepe.com.