Calcolare quanto spazio occupa ciascuna sottocartella di una directory — utile per un pannello di amministrazione, o semplicemente per capire dove sta crescendo lo spazio su disco di un progetto — sembra richiedere una funzione ricorsiva scritta a mano. La libreria SPL di PHP, però, include già gli strumenti per farlo in poche righe, con un'API pensata apposta per questo tipo di attraversamento.
RecursiveDirectoryIterator e RecursiveIteratorIterator
La coppia di classi da conoscere è RecursiveDirectoryIterator, che sa scendere nelle sottocartelle, e RecursiveIteratorIterator, che la trasforma in un iteratore "piatto" su cui si può semplicemente scorrere con un foreach. Il flag LEAVES_ONLY fa sì che vengano restituiti solo i file, non le cartelle intermedie:
<?php
declare(strict_types=1);
function dimensioneCartella(string $percorso): int
{
$totale = 0;
$iteratore = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$percorso,
FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS
),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iteratore as $file) {
if ($file->isFile()) {
$totale += $file->getSize();
}
}
return $totale;
}Il flag SKIP_DOTS evita che . e .. vengano considerati come voci da attraversare — un errore facile da commettere scrivendo la ricorsione manualmente, che porterebbe a un ciclo infinito.
Un dettaglio da non sottovalutare: i permessi
Su un filesystem condiviso, alcune sottocartelle potrebbero non essere leggibili dall'utente con cui gira PHP: RecursiveDirectoryIterator lancia un'eccezione UnexpectedValueException quando incontra una cartella a cui non può accedere. In uno script pensato per girare anche su strutture di cartelle non completamente sotto il proprio controllo, conviene avvolgere la creazione dell'iteratore in un try/catch e saltare semplicemente la cartella incriminata, continuando con le altre.
Formattare la dimensione in modo leggibile
Il numero di byte grezzo va convertito nell'unità più leggibile (KB, MB, GB) in base alla grandezza, una piccola funzione di utilità che si ritrova spesso in progetti diversi:
function formattaDimensione(int $byte): string
{
return match (true) {
$byte >= 1_073_741_824 => number_format($byte / 1_073_741_824, 2) . ' GB',
$byte >= 1_048_576 => number_format($byte / 1_048_576, 2) . ' MB',
$byte >= 1_024 => number_format($byte / 1_024, 2) . ' KB',
default => $byte . ' B',
};
}Un avviso prima di metterlo online
Uno script come questo, che espone dimensioni e nomi di cartelle del server, è comodo durante lo sviluppo ma non va mai lasciato raggiungibile pubblicamente in produzione: rivela informazioni sulla struttura interna del filesystem che non riguardano un visitatore qualunque. Va protetto dietro autenticazione admin, oppure eseguito da riga di comando (CLI) invece che come pagina web pubblica.