Standard PHP Library From A to Z
What is SPL
The Standard PHP Library (SPL) is a collection of interfaces and classes that are meant to solve common problems.
SPL aims to implement some efficient data access interfaces and classes for PHP. Functionally, it is designed to traverse aggregate structures (anything you want to loop over).
Why SPL:
The following PHP functions are the most popular and useful. SPL offers the same functionality in an easy and Object-oriented way.
1. Array functions
2. File System functions
3. Directory functions
4. Regular expression functions
5. And some other
The above are the most useful functions of PHP. But they are separate from each other and also difficult to remember their arguments and argument positions. But SPL bound them together and there is no need to pass arguments to every method because they are methods of one class. For example to get information about a file in SPL.
$ob=new FilesystemIterator('path/file.txt');
$ob->getFilename() // for file name
$ob->getSize() //file size in bytes
$ob->getExtension() // file extension like jpg, png, PHP,html, js etc
For the benefit of learning we discuss SPL in four part
1. Interface
Interfaces are implemented in all SPL iterators. Before learning any iterator, let’s learn about some common interfaces. So it would be helpful later to learn those iterators who implement these interfaces.
Iterator interface
Anything that can be iterated must implement this interface or its child interface. Common methods are
Current(): Return the current Element (current value).
Key(): Return the key/index of the current element
Next(): Move the cursor forward to the next element
Rewind(): Rewind the cursor to the first element of the iterator.
Valid(): checks have there is any element left. If so then return true otherwise return false.
OuterIterator
Extends Iterator and only has one special method getInnerIterator(). Which will get any child or inner iterator( if exists). Recursive iterators implement this interface to get inneriterator.
RecursieIterator
Extends from the Iterator interface and it has two special methods getChildren() and hasChildren() which is very important for Recursive Iterator. The implementer class of this interface can deal with multi-dimensional data(like multi-dimensional array or directories with lots of sub-directories).
SeekableIterator
Extends from the Iterator interface and can seek or search any element by using its seek() method. For example, to get any element of an array, give its index position it will return its value.
Array Access interface
Array Access interface checks whether an index/offset exists by its offsetExists() method, gets an index value by offsetGet(), set a value to a particular index by offsetSet() or can unset an offset/index value by offsetUnset() method.
Serializeable
Classes that implement this interface no longer support __sleep() and __wakeup() magic methods.
Serialize() should be called whenever an instance needs to be serialized and unserialize() method should be called when data need to be unserialized.
Countable
The count() method can be used to determine how many elements the current object has.
2. Data Structure
What is data structure?
In computer science, a data structure is a particular way of organizing data in a computer so that it can be used efficiently. It manages a large amount of data efficiently.
Why Use Data structure?
Quoted from Wikipedia
Data structures are generally based on the ability of a computer to fetch and store data at any place in its memory, specified by a pointer — a bit string, representing a memory address that can be itself stored in memory and manipulated by the program. Thus, the array is based on computing the addresses of data items with arithmetic operations; while the linked data structures are based on storing the addresses of data items within the structure itself.
To summarize, data structures utilize memory directly, whereas arrays use memory indirectly through algorithm operations.SplDoublyLinkedList
A linked list is a data structure consisting of a group of nodes which together represent a sequence. Each node is composed of a data and a reference (a link) to the next node in the sequence. This structure allows for the efficient insertion or removal of elements from any position in the sequence.
Why Link list rather than an array?
The main benefit of a link list over an array is that it can be easily inserted or removed without reallocation or reorganization of the entire structure. Whereas, insertion and removal in an array need to reallocate and reorganize its entire structure. Linked lists allow the insertion and removal of nodes at any point in the list. On the other hand, an array use algorithm to insert and remove in memory not directly.
Read this StackOverflow article for more
SplHeap
A heap is an untidy collection of objects placed haphazardly on top of each other.
It is an abstract class that implements common logic for a standard binary heap data structure, its abstract method compare() compares nodes by given logic so that nodes are properly arranged within the heap.
This class implements iterator and countable interface.
It would be better to illustrate its use by example.
class priority extends SplHeap
{
public function compare($array1, $array2)
{
if ($array1['age'] > $array2['age'] && $array1['salary'] > $array2['salary']) {
return 1;
} elseif ($array1['age'] == $array2['age']) {
return 0;
} else {
return -1;
}
}
}
$employee = new priority();
$employee->insert(array('age' => 22, 'salary' => 200000));
$employee->insert(array('age' => 30, 'salary' => 51000));
$employee->insert(array('age' => 30, 'salary' => 50000));
$employee->insert(array('age' => 29, 'salary' => 55000));
$employee->top();
while ($employee->valid()) {
print_r($employee->current());
$employee->next();
}
Here compare() methods takes two elements to compare. We have a multi-dimensional array which has a nested array and all of them have age and salary index. We will give priority high that child array’s age index is greater than others. It compares with one another so in the end proper element get on top.
If element1 is greater than element2 then we return 1 which means element 1 will be on top of element2. If not then return -1 which will make element2 to the top. If both of them are equal we return 0 which means they are equal and have the same level of priority. We can set the lowest first just changing greater than(>) to less than(<).
Play with this compare method for better understanding.
SplMinHeap and SplMaxHeap
These classes extend SplHeap and call its parent’s method compare() internally for keeping minimum and maximum on the top respectively. SplMinHeap will arrange values from lowest to highest and SPLMaxHeap does the opposite.
$maxHeap = new SplMaxHeap();
$maxHeap->insert(80);
$maxHeap->insert(60);
$maxHeap->insert(850);
$maxHeap->insert(250);
$maxHeap->insert(180);
foreach ($maxHeap as $hip) {
echo $hip . "<br>";
}
/*
output
850
250
180
80
60
*/
SplPriorityQueue
Another SplHeap-derived class is SplPriorityQueue, which sorts the data by priority. With the setExtractFlags() method, you can choose what to extract:
- EXTR_DATA (only the data)
2. EXTR_PRIORITY: only the priority value
3. EXTR_BOTH: both (Extract an array containing both)
This class implements iterator and countable interface.
For example, if you are searching in a string or array of strings and you want to give priority (those who have the most matches should come first) in an array then this class will be helpful.
Firstly, create an array iterator which will be full of some long string.
After that, search within the array using RegexIterator.
Finally, count how many match worlds are found in the current item and give them priority based on it.
That’s all.
$array = array(
"It so loop developer and designer and programmer Php is very fast growing language now",
"Spl is a libray of php.It so loop developer and designer and programmer",
"lack of good tutorial of spl discurage php developer to use it",
"In php manual, array,filesystem and direcory functions tutorial are avaiable ",
"we hope php community will take care of this spl tutorial .",
);
$topemp = new SplPriorityQueue();
$topemp->setExtractFlags(SplPriorityQueue::EXTR_DATA);
$ait = new ArrayIterator($array);
$regex = new RegexIterator($ait, '/(spl|php|tutorial)/', RegexIterator::ALL_MATCHES);
foreach ($regex as $key => $value) {
if (is_array($value) && count($value[1]) > 0) {
$realValue = $ait->offsetGet($key);
$topemp->insert($realValue, count($value[1])); //how many element found from string .More element found will give more priority. }
}
print_r($topemp);
//for just real content
foreach ($topemp as $key => $value) {
echo $value . "<br>";
}
}
After seeing the output you will wonder how accurate our small sorting algorithm is. In the above, instead of an array and simple regex expression, you can scan a directory and perform complex regex expression on each .html or .php file for searching.
SplObjectStorage
SplObjectStorage is what its name says: a storage class for storing objects. It stores a unique hash for each instance (like spl_object_hash()) to be able to identify object instances.
More information about SPL Data structure classes
3. Iterators
An iterator is an object that traverses a container, particularly lists like array, directory, xml tree.
Recursive: Recursion is something that repeats itself. Like a function that calls itself from within itself. Specially designed for multi-level data structure like multi-dimensional array or directory those have many subdirectories and files. It is a fancy way of saying “Do this thing again until it's done”.
Non-recursive/Normal iterator: Only its current label will iterate not in depth. Ideal for single or simple data structure those does not have nested child.
PHP has non-”recursive” iterator, such as ArrayIterator and FilesystemIterator. There are also “recursive” iterator such as the RecursiveArrayIterator and RecursiveDirectoryIterator. Later have methods enabling them to be drilled down into, the former does not.
There are two types of Iterator
1.Independent Iterator:
This type of iterator does not need the help of other Iterators iterator to finish its work.
∙ ArrayIterator /RecuriseArrayItertor
∙ DirectoryIterator / RecursiveDirectoryIterator ,
∙ FileSystemIterator
∙ GlobIterator
2. Helper Iterator:
Helper Iterators are built for certain work so that Independent iterators can work more effectively and efficiently with the help of these helper iterators.
∙ AppendIterator :Join Two or more intrator.
∙ CachingIterator / RecursiveCachingIterator : cached another iterator in memory.
∙ CallbackFilterIterator / RecursiveCallbackFilterIterator : filter element of another iterator by a callback function.
∙ FilterIterator / RecursiveFilterIterator : filter element of another iterator by the accept method. This class cannot be instantiated but extended. Child Class must define accept method for filtering their values.
∙ InfiniteIterator : Iterate an iterator infinite number. But practically it uses limititerator to set the maximum number.
∙ IteratorIterator /RecursiveIteratorIterator : RecursiveIteratorIterator loop over a tree, IteratorIterator loop over a list.
∙ LimitIterator: Limit the number of iteration of another iterator. Like if an arrayIterator just needs the first five elements to iterate then this can be used. ∙ MultipleIterator: An Iterator that sequentially iterates over all attached iterators
∙ NoRewindIterator: If an iterator needs a one-time iteration process then this is helpful. Because it does not rewind when reaches its end position. Second-time iteration will give the empty result.
∙ ParentIterator
∙ RegexIterator / RecursiveRegexIterator: Can be used to filter any iterator element by regular expression.
∙ RecursiveTreeIterator
ArrayIterator/RecursiveArrayIterator
ArrayIterator Implements ArrayAccess, seekableIterator, serializeable, countable interface.
So the methods of these interfaces are available in this class which discuss above. ArrayIterator only deals with the one-dimensional array. RecursiveArrayIterator extended from arrayIterator which will deal with multi-dimensional array with its hasChildren() and getChildren() methods. hasChildren(): Check Whether or not this current element has a nested array if so it return true.
getChildren(): Get the Current element nested child or array.
$country = array(
'bangladesh' => array('capital' => 'Dhaka', 'language' => '', 'population' => '15crore', 'currency' => 'Taka'),
'India' => array('capital' => 'New Delhi', 'language' => 'Hindi', 'population' => '130crore', 'currency' => 'Rupi'),
'pakistan' => array('capital' => 'Islamabad', 'language' => 'Urdu', 'population' => '18crore', 'currency' => 'Rupi'),
'China' => array('capital' => 'Baijing', 'language' => 'Chinise', 'population' => '135crore', 'currency' => 'Yen'),
);
$rit = new RecursiveArrayIterator($country);
while ($rit->valid()) {
if ($rit->hasChildren()) {
$child = $rit->getChildren();
while ($child->valid()) {
echo $rit->key();//will get the country name
echo $child->key() . " : " . $child->current();
$child->next();
}
} else {
echo $rit->key() . " : " . $rit->current() ;
}
$rit->next();
}
InfiniteIterator and LimitIterator
These two iterators are saying what they do. Here is the battle of limited vs unlimited. But in programming infinite loop is dangerous. Here we are going to combine these two.
Suppose, we need only two country data from the country array. Then limit iterator comes to play. It works exactly array_slice() functions do. getInnterIterator(): Get inner iterator
getPosition(): Return the current position
$rit = new RecursiveArrayIterator($country); //here we use previous country array.
$limited = new LimitIterator($rit, 0, 2); //second param is offset and third param is limit
echo '<pre>';
foreach ($limited as $key => $value) {
// $limited->getInnerIterator(); will get all four country.Because they are sperate inner iterator
if (is_array($value)) {
foreach ($value as $nkey => $nvalue) {
echo $nkey . " => " . $nvalue;
echo $limited->getPosition(); //will tell the parent index positon in main array.
}
echo '<br>';
} else {
echo $value;
echo $limited->getPosition(); //will index positon in actual array.
}
}
Visit the manual for more
If you need an array two or more times to iterate then infiniteIterator is useful. Suppose we want to iterate seven days of the week within a given range of date. See the example from the PHP manual.
CachingIterator/NoRewindIterator
Cachingiterator comes with one special method getCache() which will get cache if this iterator previously iterate over. N.B:(getCache()method only work if FULL_CACHE constant set as Flag of Cachingiterator.)
$dwarves = [1 => 'Grumpy', 2 => 'Happy', 3 => 'Sleepy', 4 => 'Bashful', 5 => 'yyy', 6 => 'Dopey', 7 => 'Doc'];
$it = new CachingIterator(new ArrayIterator($dwarves), CachingIterator::FULL_CACHE);
$it->offsetSet('Cal', 'Kathy');
foreach ($it as $offset => $value) {
echo 'Original: ' . $offset . ' == ' . $value . "\n";
}
foreach ($it->getCache() as $offset => $value) {
echo 'Cache: ' . $offset . ' == ' . $value . "\n";
}
If you need an iterator that only iterates once in its life then NoRewindItertor is for you. Trying to iterate a second time will give null values. Because it does not call rewind internally and no way to call it manually also.
$array = array(20, 30, 80, 40, 60, 99, 22, 16, 29, 32, 77, 32, "5ooo5", "oops88");
$ait = new ArrayIterator($array);
$norewind = new NoRewindIterator($ait);
foreach ($norewind as $value) {
echo $value . ", ";
}
echo '<br>end of first loop';
foreach ($norewind as $value2) {
echo $value2 . ", ";
}
AppendIterator and Multiple Iterator
Although Append and Multiple words seem similar but here its different from each other. Append Iterator append one or more iterators into one iterator what array_merge() does.
Common Methods of AppendIterator:
Append(): Add an iterator
getArrayIterator() : Return inner structure of appended iterators as an array.
getIteratorIndex(): Will return the parrent arrays index position not element index position
$bangladesh = new ArrayIterator(array('Tamim', 'Sakib', 'captain' => 'Musfiqur'));
$india = new ArrayIterator(array('Gamabir', 'Kholi', 'pujara', 'captain' => 'Dhoni', 'Kumar'));
$ap = new AppendIterator;
$ap->append($bangladesh);
$ap->append($india);
$arrays = $ap->getArrayIterator();
while ($ap->valid()) {
echo $ap->getIteratorIndex() . " . " . $ap->key() . '=> ' . $ap->current() . "<br>";
$ap->next();
}
Whereas, Multiple iterator also append/ attach iterator but in different style. It treat its iterator as source and then make each single elment as array by taking one value from each iterator. Does all attach iterator has same amount of element it depends on Constant passed on its Constructor. For example, if you have three different array contain ids, fruits name and prices respectively and you want to take id, fruit name and price and make a array of product info then this iterator will for you.
$ait_id = new ArrayIterator(array('c1001', 'c1002', 'c1003'));
$ait_name = new ArrayIterator(array('apple', 'orange', 'banana'));
$ait_units = new ArrayIterator(array(756, 996, 2345));
$mit = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
$mit->attachIterator($ait_id, "ID");
$mit->attachIterator($ait_name, "NAME");
$mit->attachIterator($ait_units, "UNITS");
echo $mit->countIterators() . "\n"; //3
if ($mit->containsIterator($ait_id)) { //true
echo "ait_id iterator attached \n";
}
foreach ($mit as $fruit) {
echo "<pre>";
print_r($fruit);
echo "</pre>";
}
/*
Result:
3
ait_id iterator attached
Array
(
[ID] => c1001
[NAME] => apple
[UNITS] => 756
)
Array
(
[ID] => c1002
[NAME] => orange
[UNITS] => 996
)
Array
(
[ID] => c1003
[NAME] => banana
[UNITS] => 2345
)
*/
//this example taken from php.net manual
attachIteraor(): append and attach an iteraotr and takes key name as its second param.
countIterator(); count how many iterator currently attached to
containsiterator(); Does an iterator attached or not.
When we upload multiple file via $_FILES then each element of that super global become an array of information. Name holds all of the file name, tmp_name contains all of the temp path and so on.At that situation this multiple iterator work perfectly. Let’s see an example.
if (isset($_FILES["files"])) {
$uploads = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
$uploads->attachIterator(new ArrayIterator((array)$_FILES["files"]["name"]), "name");
$uploads->attachIterator(new ArrayIterator((array)$_FILES["files"]["size"]), "size");
$uploads->attachIterator(new ArrayIterator((array)$_FILES["files"]["type"]), "type");
$uploads->attachIterator(new ArrayIterator((array)$_FILES["files"]["tmp_name"]), "tmp_name");
$uploads->attachIterator(new ArrayIterator((array)$_FILES["files"]["error"]), "error");
foreach ($uploads as $file) {
echo htmlspecialchars($file["name"]) . " = {$file["size"]} bytes<br/>";
}
} //this example
SplFileInfo, SplFileObject, DirectoryIterator, FilesystemIterator
Splfileinfo are the base class of all Object oriented file system class in php.
This class makes programmers life easier for handling file.
Most useful methods are:
getBasename (): Return only file name. To remove suffix from file name give suffix Name it to its optional parameter. getExtension(): File extension like (photo.jpg) will return jpg
getType(); if current element is file then return file or if it is a directory then return dir.
getFilename (): Return File name
getPath (): return its parent path
getPathname (): return current file path
getRealPath () ; return the full path as realpath() does.
getSize () : file of the size in byets.
isDir()/isExecutable()/isFile()/isReadable()/isWritable(): check whether it is or not .Return only true if success otherwise false.
$file = new SplFileObject('images/seashore.jpg', 'r');
echo $file->getBasename(); //seashore.jpg
echo $file->getFilename(); //seashore.jpg
echo $file->getExtension(); //jpg
echo $file->getType(); //file
echo $file->getPath(); //images
echo $file->getPathname(); //images/seashore.jpg
echo $file->getRealPath(); // C:\xampp\htdocs\manual\spl\images\seashore.jpg
echo $file->getSize(); // return file size in bytes divided it with 1024 to convert in KB
echo $file->isDir(); //FALSE this is not a Directory
echo $file->isExecutable(); //FALSE this is not a Executable File
echo $file->isFile(); //TRUE Yes it is a file
echo $file->isReadable(); //TRUE Yes it is Readable
echo $file->isWritable(); //FALSE Because it open
N:B: Before start please see the file permission mode.
Why SPL file system Iterators rather than procedural file system functions?
This above and all of its child class method are just build to make php more object oriented programming.n Same filesystem functionality already exist in php but in procedural style and separate from each other. For example to know file path, extension, size and etc we have to pass file name with its path into all of the functions because they are separate from each other. But in we can check all of them by using only one object. That makes programmer life easier. Moreover all of the class can be extended to fulfill any requirement.
If you think this is helpful let’s explore more.
SplFileInfo SplFileObject DirectoryIterator FilesystemIterator
SplfileObject:
This class extends from SplFileInfo class and added more method for Reading and writing in a particular file.
Useful Constant:
SKIP_EMPTY: Skips empty Lines in the file.
READ_CSV: Read Lines as CSV Rows
Most common and useful method of this class is:
Fgetc():Get character from a file. Useful for reading file character by character.
Fgets()/Fgetss():Get line from a file. Useful for reading file line by line. To strip any HTML tags from line use fgetss() method.
Fgetcsv(): Work same as fgets() and fgetss() does but parse file as CSV fields.
Fread(): Read from file
Frwrite():Write to file.
setFlasgs(): Set a flag which is one of above constant.
setCSVControl():Set how csv file will be parsed
seek(): Read a specific line in the file like 2(third line) .
$file=new SplFileObject('readme.txt','a+');
echo $file->fgetc(); // W because it is the first character of the file
echo $file->fgets(); //elcome To Spl tutorial.We did not get W because our current popinter is in e.It move Forward because of above method.
$file->next();
echo $file->fgets();
echo $file->fgetss(); //Strip any html.Otherwise it is same as fgets
//$file->next();
//echo $file->fread(10); //Only PHP 5.5.1 and above otherwise it throw an undefine method error. Read file by byte
$file->seek(0); //set cursor to first line of file;
echo $file->fgets();
$file->fwrite("\n Good Bye Everybody"); //write a line at the end of file because we give a+ as file open mode.
IteratorIterator/RecursiveIteratorIterator/RecursiveTreeIterator
Lets continue with an example.
$rit = new RecursiveArrayIterator($country);
$rrit = new RecursiveIteratorIterator($rit);
foreach ($rrit as $key => $value) {
echo $value;
}
Let’s give responsibility to RecursiveIteratorIterator whether or not there have a child iterator. It will traverse all of the tree and get value. RecursiveIteratorIterator accept a mode as second parameter and a Flag as third parameter of its constructor. Both of them are optional. MODE
RecursiveIteratorIterator::LEAVES_ONLY : The default. Lists only leaves in iteration
RecursiveIteratorIterator::SELF_FIRST : Lists leaves and parents in iteration with parents coming first.
RecursiveIteratorIterator::CHILD_FIRST : Lists leaves and parents in iteration with leaves coming first.
FLAG:
RecursiveIteratorIterator::CATCH_GET_CHILD
Most useful methods of RecursiveItratorIterator are:
setMaxDepth()/getMaxDepth() /getDepth():
An multi-dimensional array may have unlimted nested array. But if we want to get values until 3rd level or a fixed level then we can set Maximum depth so our loop untill fetches that level if it reaches its maximum depth it will start next top level element. We can get where we are by using getDepth() method. Like if we are in 3rd level then we can get value 3 if we call getDepth() method.
callHasChildren() / callGetChildren() :
Does the called element has Children within it if so then get Called element children. That’s all these two methods do.
$array = array(
array('one' => 1, 'two' => array(
'twenty' => 20, array(
'twohundread' => 200,
),
)),
'three' => 3,
'four' => 4,
);
$recursiveArray = new RecursiveArrayIterator($array);
$rii = new RecursiveIteratorIterator($recursiveArray, RecursiveIteratorIterator::LEAVES_ONLY);
$rii->setMaxDepth(3);
while ($rii->valid()) {
if ($rii->callHasChildren()) {
$child = $rii->callGetChildren();
echo $child->current();
echo ' Current Depth is : ' . $rii->getDepth();
$child->next();
} else {
echo $rii->current();
echo ' Current Depth is : ' . $rii->getDepth();
}
echo '<br>';
$rii->next();
}
RecursiveTreeIterator extends from RecursiveIterator and allows iterating over a RecursiveIterator to generate an ASCII graphic tree.Lets see an example:
There have couple of method to set prefix and post fix and by this you can modify the appearance of graphic tree. This iterator have limited real work use.
$man = array(
array('id' => 4, 'age' => 20, 'name' => 'younus', 'profession' => 'student',
'child' => array('id' => 44, 'name' => 'khan younus', 'age' => 29,
'grandChild' => array('id' => 444, 'name' => 'G younus', 'age' => 16,
'grandgrandchild' => array('id' => 4444, 'name' => 'khan Digital', 'age' => 9,
'grandgrandgrandchild' => array('id' => 44444, 'name' => 'DOS Digital', 'age' => -99))))),
array('id' => 5, 'age' => 88, 'name' => 'rahim', 'profession' => 'retired army',),
);
$ait = new RecursiveArrayIterator($man);
$tree = new RecursiveTreeIterator($ait, RecursiveTreeIterator::BYPASS_KEY);
echo '<pre>';
$tree->setPrefixPart(RecursiveTreeIterator::PREFIX_MID_LAST, " - ");
foreach ($tree as $key => $value) {
echo $value . $tree->getEntry() .
"<br>";
}
FilterIterator/RecursiveFilterIterator/parentIterator/CallbackFilterIterator/RecursiveCallbackFilterIterator
FilterIterator is the parent of above iterators and it extends from iteratoriterator .Its powerful abstract method accept() make is super power. By using its accept() method, element of an array or directory can be filtered based on some condition. This is an abstract class.
class ArrayFilter extends FilterIterator
{
public $minAge = 29;
public $minSalary = 35000;
public function accept()
{
$current = parent::current();
if (is_array($current) && isset($current['age']) && $current['age'] > $this->minAge && isset($current['salary']) && $current['salary'] > $this->minSalary) {
return $current;
}
}
}
Description: Here we only accept if element is an array and fulfill our given condition. To deal with Recursive Independent iterator use RecursiveFilterIterator which came up with two additional method that is hasChildren() and getChildren()
$employee = array(
array("name" => "sams", "age" => 22, "salary" => 25000),
array("name" => "Karim", "age" => 30, "salary" => 18000),
array("name" => "Meena", "age" => 30, "salary" => 90000),
array("name" => "Raju", "age" => 29, "salary" => 25500),
array("name" => "Mithu", "age" => 45, "salary" => 25000),
array("name" => "Akidul", "age" => 40, "salary" => 50000),
array("name" => "google", "info" => 'Giant It company the the world based on new york ', "employee" => 3000),
array("name" => "baidu", "info" => 'largest Search engine in china', "employee" => 2500),
);
echo '<pre>';
$ait = new ArrayIterator($employee);
$afil = new ArrayFilter($ait);
foreach ($afil as $key => $value) {
print_r($value);
}
/*
Output//
Array
(
[name] => Meena
[age] => 30
[salary] => 90000
)
Array
(
[name] => Akidul
[age] => 40
[salary] => 50000
)
*/
Description: Code is simple enough to read and understand. In real world you may get array of values from your database and you want some kind of more filtering then this iterator class is for you.
CallbackFilterIterator accept a callback function as a second parameter of its construction to filter element.
$ait = new ArrayIterator($employee);
$afil = new CallbackFilterIterator($ait, function ($current, $key, $it) {
if (is_array($current)) {
if (isset($current['age']) && $current['age'] > 29 && isset($current['salary']) && $current['salary'] > 35000) {
return $current;
}
}
});
foreach ($afil as $key => $value) {
print_r($value);
}
Now lets see an example of recursive iterator:
$rdir = new RecursiveDirectoryIterator("./images");
echo '<pre>';
$callBack = new RecursiveCallbackFilterIterator($rdir, function ($current, $key, $it) {
if ($current->isDir()) {
return TRUE;
}
$size = 100 * 1024; //1024 bytes is equal to one 1 KB
return $current->isFile() && $current->getSize() > $size && preg_match('/hot/', $current->getFilename());
});
$rsive = new RecursiveIteratorIterator($callBack);
foreach ($rsive as $key => $value) {
if ($value->isDir()) {
continue;
}
echo $value->getFilename() . ' |=> size:' . ($value->getSize() / 1024) . "<br>";
echo '<img src="' . $value->getPathname() . '">';
}
Description: Here we filter files within a directory recursively with the help of RecurisiveDirectoryIterator, RecursiveCallbackFilterIterator and finally use RecursiveIteratorIterator for showing result easily.
We only accept if it is a file and its size is less then greater than 100kb and it contains the word hot.
RegexIterator/RecursiveRegexIterator
Regular expression is pretty good for filtering element. SPL RegexIterator gives us opportunity to filter any iterator of spl based on regex expression. RegexIterator Accept a flag as its second argument of constructor.
Available flags are
RegexIterator::MATCH => Only execute match (filter) for the current entry
RegexIterator::GET_MATCH => Return the first match for the current entry (like preg_match())
RegexIterator::ALL_MATCHES => Return all matches for the current entry
RegexIterator::SPLIT => Returns the split values for the current entry
RegexIterator::REPLACE => Replace something by using its replacement property
RegexIterator::USE_KEY => Array key will be use instead of value
$rdir = new DirectoryIterator("./images/id");
echo '<pre>';
$regex = new RegexIterator($rdir, '/(\d{4})(-)(\d{2})(-)(toll)/', RegexIterator::MATCH);
foreach ($regex as $key => $value) {
echo $value->getFilename() . ' |=> size:' . ($value->getSize() / 1024) . "<br>";
echo '<img src="' . $value->getPathname() . '">';
}
Description: Here we only accept if any images start with 4 digit then a hypen(-) again 2 digits followed by hipen(-) again and finally word toll. This is just a format to show how regex work in Iterator.You may need custom regex expression to filter items in a directory.
Regex Replace is very powerful tool to change any element index/key word positioning. Let’s see an example
$rdir = new DirectoryIterator("./images/id");
echo '<pre>';
$regex = new RegexIterator($rdir, '/(\d{4})(-)(\d{2})(-)(toll)(.)(jpg|png|jpeg)/', RegexIterator::REPLACE);
$regex->replacement = '$3-$2-$1';
$array = iterator_to_array($regex);
print_r($array);
Description: Before this please take a look how regex replace work.
Conclusion:
I inspired to write this tutorial because the lacking of SPL tutorial in the web. When I discover the awesome features of spl then I realize that it should be told to the php community. I have struggled to find the perfect example. Moreover, some of my example had taken from others website.