note 44842 deleted from ref.spl by salathe
| From: | salathe@php.net | Date: | Tue, 16 Feb 2010 10:59:23 +0000 |
| Subject: | note 44842 deleted from ref.spl by salathe | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-166002@lists.php.net to get a copy of this message | ||
Note Submitter: mastabog at hotmail dot com
Reason: 0
----
Marcus Boerger has done a wonderful job developing the SPL. He also provided many examples using the
SPL that can be found in the php5 sources. Just unpack the sources and in the ext/spl/examples
directory you have some very nice ones. Thank you Marcus for all your efforts!
Now, a contribution of mine (i think it will be implemented later anyway). The
RecursiveIteratorIterator could use a depth limit option. Very useful in many situations (e.g. show
just the 1st subdirectory of a list of dirs). I'm sure this can be done in other ways.
Here's my 2 cents:
<?php
/**
* Limit Depth RecursiveIteratorIterator class
*
*/
class LimitRecursiveIteratorIterator extends RecursiveIteratorIterator
{
protected $depth_limit;
/**
* No depth limit by default
*
**/
public function __construct (Iterator $it, $mode = RIT_SELF_FIRST, $depth_limit = -1)
{
parent::__construct($it, $mode);
$this->depth_limit = $depth_limit;
}
/**
* After the call to next() if depth is bigger than limit then
* just skip all subIterators for that depth until depth end.
*
**/
public function next ()
{
parent::next();
if ($this->getDepth() == $this->depth_limit)
{
while ($this->getSubIterator()->valid())
$this->getSubIterator()->next();
parent::next();
}
}
}
?>
Then you can try this:
<?php
/**
* Directories only filter iterator class
*
*/
class DirectoriesOnlyIterator extends FilterIterator implements RecursiveIterator
{
public function __construct ($path)
{
parent::__construct(new RecursiveDirectoryIterator($path));
}
public function accept()
{
return $this->getInnerIterator()->hasChildren();
}
public function hasChildren ()
{
return $this->getInnerIterator()->hasChildren();
}
public function getChildren ()
{
return new self($this->getInnerIterator()->getPathname());
}
}
$it = new LimitRecursiveIteratorIterator(new DirectoriesOnlyIterator('c:'),
RIT_SELF_FIRST, 2);
// list all dirs and 1st subdir of the c: drive (might take a while depending on how many you have)
foreach ($it as $key => $value)
{
echo str_repeat(' ', $it->getDepth()) . "$value\n";
}
?>
This is considerably faster than using just the RecursiveIteratorIterator and ignoring yourself in
the foreach loop the values for depth > limit (i.e. if($it->getDepth() > $limit)
continue;). that is because the class will still parse everything up to the last depth level of
every head node.
You can then play and display nice trees (might need a while() loop or the CachingRecursiveIterator
to detect end nodes/leafs). There is already an example provided by Marcus in the ext/spl/examples
dir i mentioned above.
Happy SPL-ing :),
Bogdan
P.S. I think some of the classes should call rewind() at instantiation time ... If you try to put a
Caching* object in a foreach loop you will lose the first/last element. Instead, you should call
rewind() and then go with a while($cit->valid()) loop and using current() and key() inside it.