I wanted to share with you a file handling code that I previously used in my own PHP application. PHP includes functions like file_get_contents() and scan_dir() that allow you to list files in the file system. However, once the file system starts to get overloaded, the functions provided by PHP unfortunately fall short in terms of performance.


To handle files without overloading the server, we need to use PHP's Iterable objects. First, we will use Symfony Finder for directory scanning, and then iterate over the files using our Iterable object.

<?php

use Symfony\Component\Finder\Finder as SymfonyFinder;

$finder = new SymfonyFinder();

$finderX = $finder
    ->files()
    ->in('files/path') // Directory to search
    ->path('/subdirectory/') // Filter subdirectories (can be specified with regex)
    ->name('*.txt') // Filter by file names (e.g., files with .txt extension)
    ->date('since 1 day ago') // Filter by modification date (e.g., files modified in the last day)
    ->depth('< 2') // Filter by directory depth (e.g., only the specified directory and one subdirectory)
    ->sortByChangedTime(); // Sort by modification time

// Here we get the Iterator object from SymfonyFinder.
$iterator = $finderX->getIterator();

// Total number of media files
$mediaCount = $iterator->count();




Now, if we have, for example, "1000" files, Finder will retrieve them. However, we also need to set a "Limitation" to specify which range of files we want from this list. For example, we retrieved the files by their addition date. But we need to add a "Pagination" so that files are fetched in batches of 40 from the beginning.


function formatSizeUnits($bytes) {
    if ($bytes >= 1073741824) {
        $size = number_format($bytes / 1073741824, 2) . ' GB';
    } elseif ($bytes >= 1048576) {
        $size = number_format($bytes / 1048576, 2) . ' MB';
    } elseif ($bytes >= 1024) {
        $size = number_format($bytes / 1024, 2) . ' KB';
    } elseif ($bytes > 1) {
        $size = $bytes . ' bytes';
    } elseif ($bytes == 1) {
        $size = $bytes . ' byte';
    } else {
        $size = '0 bytes';
    }

    return $size;
}

// File range limit
$filesLimit = 40;

// File range start
$filesStart = 0;

// File List
$fileList = [];

$splFileInfo = new \LimitIterator($iterator, $filesStart, $filesLimit);

foreach ($splFileInfo as $file) {
    $fileList[] = [
        'name' => $file->getFilename(),
        'size' => formatSizeUnits($file->getSize()),
        'type' => mime_content_type($file->getRealPath()),
    ];
}

var_export($fileList);


By setting it up this way, we will no longer impose a heavy load on the server on the PHP side and will be able to retrieve the desired range of files efficiently.