Salta al contenuto principale

Utilizzare l'autoload di Composer per gestire le dipendenze di un progetto PHP

Profile picture for user luca77king

L'autoloading è una funzionalità fondamentale nello sviluppo con PHP e può semplificare notevolmente il processo di gestione delle dipendenze del progetto. In questo articolo esamineremo come utilizzare Composer per implementare l'autoloading delle classi in modo da non dover più importare manualmente i file. Ti fornirò una guida passo-passo per configurare il tuo ambiente di sviluppo e comprendere i diversi tipi di autoloading disponibili con Composer.

Quando si sviluppano applicazioni PHP, è spesso necessario utilizzare librerie di terze parti. Normalmente, per utilizzare queste librerie nella propria applicazione, è necessario includerle mediante l'uso di istruzioni come require o include. Tuttavia, questo approccio può diventare problematico man mano che l'applicazione cresce, poiché l'elenco di dichiarazioni require o include diventa sempre più lungo e difficile da gestire. Inoltre, questo metodo carica l'intera libreria nell'applicazione, comprese le parti che non vengono utilizzate aumentando l'utilizzo di memoria dell'applicazione.

Per evitare i problemi  appena descritti, sarebbe ideale caricare le classi solo quando sono effettivamente necessarie. Ecco dove entra in gioco l'autoloading. In pratica, quando si utilizza una classe in un'applicazione, l'autoloader verifica se è già stata caricata e, se non è così, carica in memoria la classe necessaria. In questo modo, la classe viene caricata al momento del bisogno, senza doverla includere manualmente. Questo processo è noto come autoloading. Utilizzando l'autoloading, non è necessario includere manualmente tutti i file delle librerie; basta includere il file autoloader che contiene la logica di autoloading, e le classi necessarie verranno incluse dinamicamente.

Implementare l'autoloading senza Composer

Forse non lo sapevi, ma è possibile implementare l'autoloading in PHP senza utilizzare Composer. La funzione spl_autoload_register() rende possibile questa operazione e permette di registrare funzioni che verranno inserite in una coda e attivate in modo sequenziale quando PHP tenta di caricare classi non ancora caricate.

Ecco un esempio per illustrare il funzionamento di spl_autoload_register():

<?php
function custom_autoloader($class) {
  $class = str_replace('\\', '/', $class);
  $elements_raw = explode('/', $class);
  $path_elements = array_map(function ($part, $index) use ($elements_raw) {
    return $index === count($elements_raw) - 1 ? $part : strtolower($part);
  }, $elements_raw, array_keys($elements_raw));
  $full_path = implode('/', $path_elements);
  include $full_path . '.php';
}
 
spl_autoload_register('custom_autoloader');
 
$objFooBar = new FooBar();
?>

Quando si tenta di istanziare la classe FooBar e questa non è ancora disponibile, PHP eseguirà in sequenza tutte le funzioni di autoloader registrate. In questo caso, verrà richiamata la funzione custom_autoloader, che include il file della classe necessario, e quindi l'oggetto verrà istanziato. Nell'esempio precedente, supponiamo che la classe FooBar sia definita nel file lib/FooBar.php.

Senza l'autoloading, sarebbe necessario utilizzare l'istruzione require o include per includere il file della classe FooBar. L'implementazione dell'autoloader nell'esempio mostrato è relativamente semplice, ma è possibile usare anche i namespace in questo modo:

<?php
function custom_autoloader($class) {
  $class = str_replace('\\', '/', $class);
  $elements_raw = explode('/', $class);
  $path_elements = array_map(function ($part, $index) use ($elements_raw) {
    return $index === count($elements_raw) - 1 ? $part : strtolower($part);
  }, $elements_raw, array_keys($elements_raw));
  $full_path = implode('/', $path_elements);
  include $full_path . '.php';
}

spl_autoload_register('custom_autoloader');

use Lib\FooBar;
$objFooBar = new FooBar();
?>

Tuttavia, non è necessario scrivere spesso il proprio autoloader, poiché Composer svolge questo compito in modo molto efficiente.

Come funziona l'autoloading con Composer

Prima di cominciare, assicurati di installare Composer sul tuo sistema se vuoi seguire gli esempi di questa guida. 

Composer offre quattro diverse opzioni per l'autoloading dei file:

  • Autoloading di file
  • Autoloading di classmap
  • Autoloading PSR-0
  • Autoloading PSR-4

Secondo la documentazione ufficiale di Composer, PSR-4 è il metodo consigliato per l'autoloading, che verrà trattato in dettaglio nella sezione successiva. In questa sezione, esamineremo brevemente le altre tre opzioni.

Per utilizzare l'autoloading di Composer, è necessario seguire i seguenti passaggi:

  1. Definire il file composer.json nella root del progetto o della libreria, che dovrà contenere le direttive per il tipo di autoloading desiderato.
  2. Eseguire il comando composer dump-autoload per generare i file necessari che Composer userà per l'autoloading.
  3. Includere la dichiarazione require 'vendor/autoload.php' all'inizio del file in cui si vuole utilizzare l'autoloading.

Autoloading di file

L'autoloading di file funziona in modo simile alle istruzioni include o require, che permettono di caricare interi file sorgente. Tutti i file sorgente specificati nella direttiva file verranno caricati ogni volta che l'applicazione viene eseguita. Questo è utile per caricare file sorgente che non contengono classi.

Per utilizzare l'autoloading di file, fornire un elenco di file nella direttiva file del file composer.json, come mostrato di seguito.

{
    "autoload": {
        "file": ["lib/Foo.php", "lib/Bar.php"].
    }
}

Come puoi vedere, nella direttiva file è possibile fornire un elenco di file che si desidera caricare automaticamente con Composer. Dopo aver creato il file composer.json nella root del progetto con il contenuto mostrato, è sufficiente eseguire il comando composer dump-autoload per creare i file di autoloading necessari, che saranno salvati nella cartella vendor. Infine, è necessario includere la dichiarazione require 'vendor/autoload.php' all'inizio del file in cui si desidera utilizzare l'autoloading di file con Composer, come mostrato di seguito.

<?php
require 'vendor/autoload.php';
  
// codice che utilizza le cose dichiarate nel file "lib/Foo.php" o "lib/Bar.php"
?>

L'istruzione require 'vendor/autoload.php' assicura che i file necessari siano caricati dinamicamente. 

Autoloading di classmap

L'autoloading di classmap è una versione migliorata dell'autoloading di file. È sufficiente fornire un elenco di directory e Composer analizzerà tutti i file presenti al loro interno. Per ogni file, Composer creerà un elenco delle classi contenute in esso e ogni volta che una di queste classi sarà necessaria, Composer carica automaticamente il file corrispondente.

Modifichiamo velocemente il file composer.json per dimostrare l'utilizzo dell'autoloader di classmap.

{
    "autoload": {
        "classmap": ["lib"]
    }
}

Eseguendo il comando composer dump-autoload, Composer legge i file presenti nella cartella lib per creare una mappa delle classi che possono essere caricate automaticamente.

Autoloading PSR-0

PSR-0 è uno standard raccomandato dal gruppo PHP-FIG per l'autoloading. Secondo questo standard, è necessario utilizzare i namespace per definire le librerie. Il nome della classe completamente qualificata deve rispecchiare la struttura <Nome del provider>(<Namespace>)*<Nome della classe>. Inoltre, le classi devono essere salvate in file che seguono la stessa struttura di directory dei namespace.

Diamo un'occhiata al seguente file composer.json.

{
    "autoload": {
        "psr-0": {
            "Tutsplus\Library": "src"
        }
    }
}

Nell'autoloading PSR-0, è necessario mappare i namespace alle directory. Nell'esempio precedente, stiamo dicendo a Composer che tutto ciò che inizia con il namespace Tutsplus\Library deve essere disponibile nella cartella src\Tutsplus\Library.

Ad esempio, se si desidera definire la classe Foo nella cartella src\Tutsplus\Library, è necessario creare il file src\Tutsplus\Library\Foo.php, come mostrato di seguito:

<?php
namespace Tutsplus\Library;
 
classe Foo 
{
    //...
}
?>

Come si può notare, questa classe è definita nel namespace Tutsplus\Library. Inoltre, il nome del file corrisponde al nome della classe. Ecco come è possibile caricare automaticamente la classe Foo.

<?php
require 'vendor/autoload.php';
  
$objFoo = new Tutsplus\Library\Foo();
?>

Composer caricherà in automatico la classe Foo dalla cartella src/Tutsplus/Library.

Autoloading PSR-4

PSR-4 è simile all'autoloading PSR-0 in quanto richiede l'utilizzo di namespace, ma non è necessario che la struttura delle directory rifletta i namespace.

Nell'autoloading PSR-0, è necessario mappare i namespace alla struttura delle directory. Come discusso nella sezione precedente, per caricare automaticamente la classe Tutsplus\Library\Foo, questa deve essere presente in src\Tutsplus\Library\Foo.php. Con l'autoloading PSR-4, è possibile abbreviare la struttura delle directory, rendendo il processo di autoloading molto più semplice rispetto all'autoloading PSR-0.

Rivediamo l'esempio precedente, facendo attenzione alle differenze.

Ecco come appare il file composer.json con l'autoloading PSR-4:

{
    "autoload": {
        "psr-4": {
            "Tutsplus\Library\": "src"
        }
    }
}

È importante notare che abbiamo aggiunto dei backslash alla fine dei namespace. La mappatura di cui sopra indica a Composer che tutto ciò che inizia con il namespace Tutsplus e Library deve essere disponibile nella cartella src. Non è quindi necessario creare le directory Tutsplus e Library. Per esempio, se si richiede la classe Tutsplus\Library\Foo, Composer cercherà di caricare il file src\Foo.php.

È importante capire che la classe Foo è ancora definita nel namespace Tutsplus\Library; è solo che non è necessario creare cartelle che imitino i namespace. Il contenuto del file src\Foo.php sarà identico a quello del file src\Tutsplus\Library\Foo.php della sezione precedente.

Come si può vedere, PSR-4 dà luogo a una struttura di cartelle molto più semplice, in quanto si può evitare di creare cartelle annidate, pur continuando a usare i namespace completi.

PSR-4 è il metodo consigliato per l'autocaricamento ed è ampiamente accettato dalla comunità PHP.