1

I am trying to create a function that removes the oldest files based on date, for a max of 30 files. I grab all the files in the dir. If there are more than 30, they get sorted by date. Then the oldest gets deleted.

public function cleanUpFolder($path){
    $files = [];
    try {
        $dir = new DirectoryIterator($path);
        foreach ($dir as $fileinfo) {
            if (!$fileinfo->isDot()) {
                $files[] = $fileinfo;
                // in here i can call any valid method like getPathname()
            }
        }
        $fileCount = count($files);
        if($fileCount > self::MAX_BACKUPS){
            // sort with the youngest file first
            usort($files, function($a, $b) {
                // in here, i can call functions like getMTime()
                // and even getPath()
                // but getPathname or getFileName return false or ""
                return $a->getMTime() < $b->getMTime();
            });
            for($i = $fileCount - 1; $i > 30; $i--){
                unlink($files[$i]->getPathname());
            }
        }        
        return true;
    }
    catch (Exception $e){
        return false;
    }
}

What is working

  1. Getting the files

What is not working

  1. Sort? I cannot tell if the sort works

  2. Calling some methods on the DirectoryIterator while looping through the $files array

It seems like putting the $fileInfo into an array, most function calls no longer work..

1 Answers1

0

I found that the $files array's values got messed up outside of the foreach loop. A var_dump of the array showed all the values were empty, which is odd. Not really a solution, but a workaround I found from this question:

$files = array();
$dir = new DirectoryIterator($path);
foreach ($dir as $fileinfo) {
    if (!$fileinfo->isDot()) {
        $files[] = array(
            "pathname" => $fileinfo->getPathname(),
            "modified" => $fileinfo->getMTime()
        );
    }
}

and then your usort becomes:

usort($files, function($a, $b) {
    return $a['modified'] < $b['modified'];
});

and your unlink becomes:

for($i = $fileCount - 1; $i > 30; $i--){
    unlink($files['pathname']);
}

=== EDIT ===

I'm not expert in PHP so this could be wrong, but the top comment of FilesystemIterator could be a clue as to why the methods are returning empty.

When you iteterate using DirectoryIterator each "value" returned is the same DirectoryIterator object. The internal state is changed so when you call isDir(), getPathname(), etc the correct information is returned. If you were to ask for a key when iterating you will get an integer index value.

FilesystemIterator (and RecursiveDirectoryIterator) on the other hand returns a new, different SplFileInfo object for each iteration step. The key is the full pathname of the file. This is by default. You can change what is returned for the key or value using the "flags" arguement to the constructor.

Richard
  • 528
  • 2
  • 15