Lo standard di programmazione PSR-4 per l'autoloading delle classi PHP
Il PSR, acronimo di “PHP Standard Recommendation“, è uno standard di programmazione promosso dal PHP-FIG (PHP Framework Interop Group), un gruppo che rappresenta dell’intera comunità PHP, che vuole definire delle regole per la scrittura di codice PHP così da facilitare la lettura e la condivisione dello stesso da parte della community degli sviluppatori.
Queste regole abbracciano vari aspetti della programmazione in PHP, come gli autoload, lo stile di scrittura, la definizione di interfacce, e così via.
Elenco delle PSR
Esistono molti PSR, vediamone in rassegna solo qualcuno. Per la lista completa di rimanda al sito PHP-FIG.
- PSR-1 – Basic coding standards
Sono linee guida standard di base su come scrivere il codice PHP. - PSR-3 – Logger interface
Lo scopo è quello di ottenere uno standard comune per il log degli applicativi in PHP. - PSR-4 – Autoloading
Definisce gli standard per la generazione di file PHP di autoloading. E' l'oggetto di questo articolo. - PSR-6 – Caching interface
Qui vengono definiti gli standard per la generazione di classi che si occupino del sistema di caching. - PSR-7 – HTTP Message interface
Anche in questo caso vengono descritte degli standard orientati alla gestione di messaggi HTTP. - PSR-13 – Hypermedia links
Sono regole per la corretta generazione di hypermedia link.
In questo articolo di occupiamo dello standard PSR-4 relativo alla generazione di file autoloading in PHP.
Lo standard PSR-4
PSR-4 fa uso dei namespace, tecnica che evita che si verifichino conflitti tra classi aventi lo stesso nome, ma appartenenti a librerie diverse.
Ecco le regole, prese dalla documentazione ufficiale, per la creazione di file per l'autoloading dei file che contengono le classi.
- Con il termine “classe” ci si riferisce a classi, interfacce, traits, and strutture simili.
- Un classe con un FULLY QUALIFIED NAME ha questa struttura, dove le backslash sono chiamate "namespace separator":
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
- deve avere un top-level namespace, conosciuto come il “vendor namespace” (quello immediatamente dopo la prima backslash)
- può avere uno o più sub-namespace names
- deve terminare con il nome di una classe
- gli underscore non hanno un significato speciale
- possiamo utilizzare caratteri alfabetici minuscioli e maiuscoli
- tutte le classi devono essere referenziate in modo case-sensitive al minusciolo e maiuscolo
- Quando si carica un file .php che corrisponde ad un FULLY QUALIFIED NAME
- Una serie contigua di uno o più namespace e sub-namespace, escluso i "namespace separator", nel FULLY QUALIFIED NAME (un "prefisso namespace") corrisponde ad almeno una "directory di base".
- I sub-namespace contigui dopo il "namespace prefix" corrispondono a una sottodirectory all'interno di una "directory di base", in cui i "namespace separator" rappresentano i separatori di directory (le slash). Il nome della sottodirectory deve corrispondere ai nomi dei sub-namespace.
- Il nome della classe finale corrisponde a un nome di file che termina con .php. Il nome del file deve corrispondere nome della classe finale.
- L'autoloader non deve generare eccezioni, non deve generare errori di alcun livello e non dovrebbe restituire un valore.
Dalla teoria, passiamo alla pratica per realizzare uno script di autoloading che carichi i file necessari per utilizzare le classi conenute al loro interno.
Esempi di PSR-4
In questo esempio vediamo un codice PSR-4 molto semplice, ma è utilie per farvi comprendere come si scrive un codice corretto.
Prendiamo una struttura del filesystem così organizzata
index.php
autocaricamento.php
Lib
Admin
Ruoli.php
User
Info.php
Nella cartella "Lib" abbiamo una sottodirectory "Admin" che contiene un file "Ruoli.php" con un namespace uguale al path in cui si trova cioè "Lib\Admin", e con una classe omonima "Ruoli"
<?php
namespace Lib\Admin;
class Ruoli{
public function __construct()
{
echo "ciao dalla classe ".__CLASS__;
}
}
?>
Quindi abbiamo una similitudine tra il namespace "Lib\Admin" e il path del filesystem "Lib/Admin"
Sempre nella cartella "Lib" abbiamo una sottodirectory "User" che contiene un file "Info.php", che ha un namespace uguale al path in cui si trova cioè "Lib\User", e con una classe omonima "Info"
<?php
namespace Lib\User;
class Info{
public function __construct()
{
echo "ciao dalla classe ".__CLASS__;
}
}
?>
Anche qui abbiamo una similitudine tra il namespace "Lib\User" e il path del filesystem "Lib/User"
Nella "index.php" includiamo la funzione "autocaricamento.php" ed istanziamo un oggetto per ognuna delle due classi utilizzando un QUALIFIED NAME (cioè hanno almeno un namespace separator, ma non all'inizio):
<?php
include "autocaricamento.php";
$obj=new Lib\Admin\Ruoli();
echo "<br>";
$obj=new Lib\User\Info();
?>
Nel file "autocaricamento.php" andremo ad inserire uno script per realizzare l'autocaricamento dei file che contengono le classi:
<?php
spl_autoload_register(
function ($nome){
require_once str_Replace("\\","/",$nome).".php";
}
);
?>
Lanciamo la index.php, la risposta della pagina sarà
ciao dalla classe Lib\Admin\Ruoli
ciao dalla classe Lib\User\Info
Spieghiamo come funziona il file di autocaricamento: quando cerchiamo di istanziare un oggetto di una classe non presente, la funzione PHP spl_autoload_register accede automaticamente alla funzione anonima di autocaricamento, e passa a questa non solo il nome della classe "Ruoli" ma anche il relativo namespace "Lib\Admin", quindi riceverà "Lib\Admin\Ruoli"
Noi appiamo che il file "Ruoli.php" che contiene la classe "Ruoli" si trova nel percorso "Lib/Admin/Ruoli.php", per cui per includere il file "Ruoli.php", dobbiamo semplicemente:
- sostituire ai "namespace separator" le slash così da costruire un path del filesystem, utilizzando la funzione str_replace
- aggiungere l'estensione .php al fondo
Così facendo la funzione farà i seguenti include:
require_once Lib/Admin/Ruoli.php;
require_once Lib/User/Info.php;
E' questa inclusione che ci consentirà di utilizzare le classi contenute in questi file.
Abbiamo così ottenuto un sistema di autoloading delle classi php rispettando lo standard PSR-4.
Riporto alcuni link al sito ufficiale, tra cui una pagina in cui è presente un esempio articolato.