SitePoint Sponsor

User Tag List

Results 1 to 14 of 14
  1. #1
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Finaly done, Recursive Directory Iterator

    Hey there,

    I've been strugling with this for over a few days now, i am working on a new framework, but my main issue with this is that it has to be able to contain itself through reflections and captures, for example, when an class is called abstract or an instance has to be made from a class this package just calls the right class for it, but my application does not use any require_once or include_once except for interfaces, so we all know that __autoload solves this problem if you know where the file you need is, if not, i wanted my application to search for it, with no matches it would throw an exception and will inform the user that this class does not exists in the project's tree scope.

    But the problem was the fact that i was not able to do an actual search from a path up to it's last director, i tried a traversable directory reader, but it just didn't fit my needs, so i did found a solution to read out an entire tree of directories and search on the found results.

    PHP Code:
    function __autoload($classNamespace){
            
    $dir = new RecursiveIteratorIterator(new RecursiveDirIterator('./'), true);
            foreach ( 
    $dir as $file ) {
                echo 
    str_repeat("--"$dir->getDepth()) . $file\n<br>";
            } 
            echo 
    "Unable to include/require : $classNamespace";
            exit(
    0);
        }
        
        class 
    DirIterator implements Iterator {
        
            protected 
    $dir;
            
            protected 
    $key;
            protected 
    $file;
            protected 
    $valid;
                
            public function 
    __construct($path) {
                
    $this->dir opendir($path);
            }
            
            public function 
    __destruct() { 
                
    closedir($this->dir);        
            }
            
            public function 
    rewind() {
                
    $this->key 0;
                
    rewinddir($this->dir);
                
    $this->next();
            }
            
            public function 
    next() {
                
    $this->key++;
                
    $this->valid false !== ($this->file readdir($this->dir));
            }
            
            public function 
    key() {
                return 
    $this->key;
            }
            
            public function 
    current() {
                return 
    $this->file;
            }
            
            public function 
    valid() {
                return 
    $this->valid;
            }
        
        }
        
        class 
    RecursiveDirIterator extends DirIterator implements RecursiveIterator {
        
            protected 
    $path;
            
            public function 
    __construct($path) {
                
    parent::__construct($path);
                
    $this->path $path;
            }
            
            public function 
    hasChildren() {
                return ( 
    is_dir($this->path '/' $this->file) &&
                        !(
    $this->file == '.' || $this->file == '..'));        
            }
            
            public function 
    getChildren() {
                return new 
    RecursiveDirIterator($this->path '/'$this->file);
            }
        } 
    This thread is pure ment for people looking for a same sort solution, you can now itterate through every level of your tree without braking it and without working with chDir();

    I got this solution from the link below, read it .... it's extremely handy :-)
    http://www.ramikayyali.com/archives/...2/25/iterators

    Hope this is usefull for some of us...
    Cheers,
    Galo
    Business as usual is off the menu folks, ...

  2. #2
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is very good approach. It may turn to be quite useful.


  3. #3
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    SPL already has RecursiveDirectoryIterator or am I missing something?

    Regarding your code, readdir is a pretty slow thing, I'd suggest trying glob() or `ls` first and degrading to readdir only if they are not available.

  4. #4
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog
    SPL already has RecursiveDirectoryIterator or am I missing something?

    Regarding your code, readdir is a pretty slow thing, I'd suggest trying glob() or `ls` first and degrading to readdir only if they are not available.

    Thanks for the input, i made a case statement with an extr parameter called "method", it's set to readdir for default so we dont get any issues.... you can specify ls or glob if you want to.

    again thanks for the input,
    Galo
    Business as usual is off the menu folks, ...

  5. #5
    SitePoint Enthusiast
    Join Date
    May 2004
    Location
    Syria
    Posts
    31
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    stereofrog's right, SPL already has a RecursiveDirectoryIterator, you should subclass it if you need it to do more. I only wrote DirIterator and RecursiveDirIterator as examples of how it's done in SPL, but you shouldn't use them when you have a native, SPL class that does the exact same thing.

    By the way, I'm glad you like the article =)
    I blog here here, and I'm happy to help.

  6. #6
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cubex
    stereofrog's right, SPL already has a RecursiveDirectoryIterator, you should subclass it if you need it to do more. I only wrote DirIterator and RecursiveDirIterator as examples of how it's done in SPL, but you shouldn't use them when you have a native, SPL class that does the exact same thing.

    By the way, I'm glad you like the article =)
    I do use it cause im extending the SPL class with my own additional functionalies as building a tree, filtering and searching for files, just some methods that don't come standard to extends the flexibilities...
    Business as usual is off the menu folks, ...

  7. #7
    SitePoint Enthusiast
    Join Date
    May 2004
    Location
    Syria
    Posts
    31
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, as long as it works, that shouldn't be a problem.
    I blog here here, and I'm happy to help.

  8. #8
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    People,

    been trying to get my search function working, and it works like a train now, the problem i had was the fact that i lost track of in which directory the found result was hiding.

    What this does is when you ask for an instance of an object through a class and the framework does not know the class for it it calls __autoload as last attempt to retreive the right file, the problem was not finding the file, returning it. The problem was the fact that when i found the file, i could still not implement (require/include) it beceause it returned the file from an Array which did not hold the right directory, this was done internally in the DirIterator class, at the __constructor, the path was provided by the Iterator every time he goes up or down a directory.

    I made a completely static/abstract class where this variable is beeing passed through in the constructor of the DirIterator, pretty handy, when i now find the file he automaticly stores the directory he's currently working in as hos directory, so doing this i have a directory to the right fiole as wel as the file, calling up on file_exsists() it actually return true now :-)

    here's the code if you might be interested, i know it's not perfect but it works im gonna leave it like this.

    PHP Code:
    function __autoload($classNamespace){
            
    $recursiveDirectory = new RecursiveDirIterator('./');
            
    $dir = new RecursiveIteratorIterator($recursiveDirectorytrue);
            
    $dir->getDepth();
            if(
    $result DirIterator::search($dir$classNamespace)){
                
    $pathToFile   DirectoryTracer::getPath() . "/" $result;
                
    $strippedPath explode("./"$pathToFile);
                
    $targetFile   =    substr($strippedPath[1], 1); 
                if(
    file_exists($targetFile)){
                    echo 
    "Found target : $targetFile<br>";
                }else{
                    echo 
    "Unable to target file : $targetFile";
                }
            }else{
                echo 
    "Unable to include/require : $classNamespace";
                exit(
    0);
            }
        }
        
        abstract class 
    DirectoryTracer{
            
            public static 
    $path;
            
            public static function 
    setPath($path){
                
    self::$path null;
                
    self::$path $path;
            }
            
            public static function 
    getPath(){
                return(
    self::$path);
            }
        }
        
        
    //Directory Iterator
        
    class DirIterator implements Iterator {
        
            protected 
    $dir;
            protected 
    $key;
            protected 
    $file;
            protected 
    $valid;
            protected 
    $method;
                
            public function 
    __construct($path$method "readdir"){
                
    DirectoryTracer::setPath($path);
                
    //echo $pathResult . "<br>";
                
    $this->method $method;
                
    $this->dir    opendir($path);
            }
            
            public function 
    search($directoryIterator$targetNamespace){
                foreach(
    $directoryIterator as $file){
                    if(
    $file != (string) "." && $file != (string) ".."){
                        
    $fileNamespace explode("."$file);
                        if((
    ucfirst($fileNamespace[0]) . ucfirst($fileNamespace[1])) === trim($targetNamespace)){
                            
    //echo "found";
                            
    return($file);
                        }
                    }
                }
            }
            
            public function 
    getPath(){
                return(
    $pathResult);
            }
            
            public function 
    createTree(){
                foreach(
    $directoryIterator as $file){
                    if(
    $file != (string) "." && $file != (string) ".."){
                        echo 
    str_repeat("&nbsp;&nbsp;&nbsp; "$directoryIterator->getDepth()) . "- <b>$file</b>\n<br>";
                    }
                }
            }
            
            public function 
    __destruct() { 
                
    closedir($this->dir);        
            }
            
            public function 
    rewind() {
                
    $this->key 0;
                
    rewinddir($this->dir);
                
    $this->next();
            }
            
            public function 
    next() {
                
    $this->key++;
                switch(
    $this->method){
                    case 
    "readdir" :
                        
    $this->valid false !== ($this->file readdir($this->dir));
                    break;
                    case 
    "ls"      :
                        
    $this->valid false !== ($this->file system('ls'$this->dir));
                    break;
                    case 
    "glob"    :
                        
    $this->valid false !== ($this->file glob("$this->dir"));
                    break;
                }
                
            }
            
            public function 
    key() {
                return 
    $this->key;
            }
            
            public function 
    current() {
                return 
    $this->file;
            }
            
            public function 
    valid() {
                return 
    $this->valid;
            }
        
        }

        
    //Recursion of the DirectoryIterator
        
    class RecursiveDirIterator extends DirIterator implements RecursiveIterator {
        
            protected 
    $path;
            
            public function 
    __construct($path) {
                
    parent::__construct($path);
                
    $this->path $path;
            }
            

            public function 
    hasChildren() {
                return(
    is_dir($this->path '/' $this->file) && !((string) $this->file == '.' || (string) $this->file == '..'));        
            }
            
            public function 
    getChildren() {
                return new 
    RecursiveDirIterator($this->path '/'$this->file);
            }
        } 
    OT : Cubex i see your codeflakes project has started, still in design phase though, can't wait to it running....

    Cheers,
    Galo
    Business as usual is off the menu folks, ...

  9. #9
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    SPL already has a RecursiveDirectoryIterator, you should subclass it if you need it to do more.
    True, true, though on the other hand, you could take the script that I posted the other day there, modify it easily to recurse over a directory structure.

    It is possible

  10. #10
    SitePoint Enthusiast
    Join Date
    May 2004
    Location
    Syria
    Posts
    31
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Galo, there's a lesson that I learned the hard way: Never, ever ever ever, start a project in design phase, nobody will participate. Codeflakes right now is in a state of hibernation, I need to get some code up and running, clean and useful design docs, and only then it can start rolling. Hopefully, we'll be seeing something soon.

    By the way, I noticed you're using a $method for reading directories? Why would you want to choose anything else other than glob() or readdir()? You should benchmark them, choose one, and stick with it. A switch statement in a directory iterator is just wasted CPU cycles IMHO.
    I blog here here, and I'm happy to help.

  11. #11
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah i know what you mean, honestly :-) and about that code, that's just there to be beta and all, im cleaning the mess right now.
    Business as usual is off the menu folks, ...

  12. #12
    get into it! bigduke's Avatar
    Join Date
    May 2004
    Location
    Australia
    Posts
    847
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Gee man, that looks like a lot of processing overhead.

  13. #13
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bigduke
    Gee man, that looks like a lot of processing overhead.
    It's just a mockup ppl....
    Business as usual is off the menu folks, ...

  14. #14
    get into it! bigduke's Avatar
    Join Date
    May 2004
    Location
    Australia
    Posts
    847
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Galo
    It's just a mockup ppl....
    I was refering to 2 levels of sub-classing

    Nice work though mate


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •