1
\$\begingroup\$

Just a small code review. Is there a better way to get all folder names?

<?php
$folders = glob(dirname(__FILE__) . '/myFolder', GLOB_ONLYDIR);
foreach ( $folders as $f ) {
    $lastDsPos = strrpos($v, DIRECTORY_SEPARATOR);
    $myFolders[] = substr($v, $lastDsPos+1);
}
\$\endgroup\$
4
\$\begingroup\$

Have you considered using SPLs RecursiveIteratorIterator and RecursiveDirectoryIterator? Like this:

$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->directory), RecursiveIteratorIterator::CHILD_FIRST);
foreach($iterator as $path){
    if($path->isDir()){
        $cache = $this->GetInfoArray($path->__toString());
        isset($cache) ? $this->listing['directories'][] = $cache : "";
        unset($cache);
    } else {
        $this->listing['files'][] = $this->GetInfoArray($path->__toString());
    }
}

This will leave you with an array with two main nodes: files and directories. I wrote this for a PHP distributed test-and-build-on-commit system and it worked well. More info on the PHP SPL Iterators can be found here: http://www.php.net/manual/en/spl.iterators.php

By the way, the GetInfoArray is this:

private function GetInfoArray($path){
    $d = new SplFileInfo($path);
    if($d->getBasename() == "." || $d->getBasename() == ".."){
        return;
    } else {
        return array(
           "pathname"    => $d->getPathname(),
           "access"      => $d->getATime(),
           "modified"    => $d->getMTime(),
           "permissions" => $d->getPerms(),
           "size"        => $d->getSize(),
           "type"        => $d->getType(),
           "path"        => $d->getPath(),
           "basename"    => $d->getBasename(),
           "filename"    => $d->getFilename()
        );
    }
}

In the end, you're left with something like this:

$this->listing['files']['smiles.jpg']['pathname'] = "/srv/www/smiles.jpg"
$this->listing['files']['smiles.jpg']['access'] = "1323546894"
$this->listing['files']['smiles.jpg']['modified'] = "2316546521"
$this->listing['files']['smiles.jpg']['permissions'] = "744"
$this->listing['files']['smiles.jpg']['size'] = "12Kb"
$this->listing['files']['smiles.jpg']['type'] = "jpg"
$this->listing['files']['smiles.jpg']['path'] = "/srv/www"
$this->listing['files']['smiles.jpg']['basename'] = "smiles"
$this->listing['files']['smiles.jpg']['filename'] = "smiles.jpg"

What the heck, heres the class itself:

# Done

class DirectoryReader{
    private $directory;
    private $listing;

    public function __construct($directory){
        try {
            $this->directory = $directory;
            $this->listing = array();
            $this->ListDir();
        } catch(UnexpectedValueException $e){
            die("Path cannot be opened.");
        } catch(RuntimeException $e){
            die("Path given is empty string.");
        }
    }

    public function GetListing(){
        return $this->listing;
    }

    private function ListDir(){
        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->directory), RecursiveIteratorIterator::CHILD_FIRST);
        foreach($iterator as $path){
            if($path->isDir()){
                $cache = $this->GetInfoArray($path->__toString());
                isset($cache) ? $this->listing['directories'][] = $cache : "";
                unset($cache);
            } else {
                $this->listing['files'][] = $this->GetInfoArray($path->__toString());
            }
        }
    }

    private function GetInfoArray($path){
        $d = new SplFileInfo($path);
        if($d->getBasename() == "." || $d->getBasename() == ".."){
            return;
        } else {
            return array(
               "pathname"    => $d->getPathname(),
               "access"      => $d->getATime(),
               "modified"    => $d->getMTime(),
               "permissions" => $d->getPerms(),
               "size"        => $d->getSize(),
               "type"        => $d->getType(),
               "path"        => $d->getPath(),
               "basename"    => $d->getBasename(),
               "filename"    => $d->getFilename()
            );
        }
    }
}

As a further note, you can also just call scandir($directory) and filter via is_dir() in a foreach.

\$\endgroup\$
6
  • \$\begingroup\$ +1 for the nice snippet, didnt know the DirectoryIterator. But before I check as correct answer. Isn't this a lot of bloat for simply showing the directory names that are inside a given directory? \$\endgroup\$ – Pinoniq Aug 14 '13 at 8:59
  • \$\begingroup\$ @Pinoniq - it is a lot of bloat...like I mentioned, this is a class for a custom built build tool, so some bloat is ok since it only gets used every now and again. Also, this gives you a whole lot more information about the file and directory, than just a listing (gives last accessed time, permissions, etc). Also, it could benefit from some optimization, considering this is the first version of the tool & class \$\endgroup\$ – jsanc623 Aug 14 '13 at 15:36
  • \$\begingroup\$ Also, can just be autoloaded and called via $dirsAndFiles = (new DirectoryReader($directory))->GetListing(); \$\endgroup\$ – jsanc623 Aug 14 '13 at 15:38
  • \$\begingroup\$ You should create gist ;) \$\endgroup\$ – Pinoniq Aug 14 '13 at 16:05
  • 1
    \$\begingroup\$ also did a quick microtime()'d test and average for a directory containing 338 leafs (files + directories), total time taken was 0.009312 - not bad at all \$\endgroup\$ – jsanc623 Aug 14 '13 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.