├── README.md
├── caching-iterator.php
├── directory-iterator-example
├── directory-iterator-recursive
│ ├── file1.txt
│ ├── file2
│ ├── file3
│ └── hello-world
├── file1.txt
├── file2.php
├── file2.txt
├── file3
├── file4.txt
├── file5
├── second-directory
│ ├── newfile.php
│ └── third-directory
│ │ └── you_found_me
└── test.php
├── directory-iterator-pt2.php
├── directory-iterator.php
├── directory-iterator
├── directory-match.php
├── directory-tree.php
├── filter-dots.php
├── filter-extension.php
└── filter-key.php
├── filter-iterator.php
├── iterator-callback.php
├── limit-iterator.php
├── observable.php
├── observer-exception-handler.php
├── observer-subject-events.php
├── pdo-iterator.php
├── recursive-caching-iterator.php
├── recursive-directory-iterator.php
├── recursive-regex-iterator.php
├── regex-iterator.php
└── simplexml-iterator.php
/README.md:
--------------------------------------------------------------------------------
1 | About this Repository
2 | =====================
3 |
4 | This repository aims to be a community wiki (a la git pull requests) of useful PHP Standard Template Library (SPL) examples. The php.net website lacks user submitted examples in the SPL department, so Queen City PHP (http://qcphp.org) is taking the initiative to provide examples and spread the word.
5 |
6 | All of the base level PHP files are working examples of their SPL iterator counterparts. Documentation will be added to the readme in the future.
7 |
8 | Regarding the Examples
9 | -------------------------
10 |
11 | Each example can be run from the command line, i.e.:
12 |
13 | ````
14 | php -f caching-iterator.php
15 | ````
16 |
17 | Which will produce example output in your console/terminal.
18 |
19 |
20 | [](https://bitdeli.com/free "Bitdeli Badge")
21 |
22 |
--------------------------------------------------------------------------------
/caching-iterator.php:
--------------------------------------------------------------------------------
1 | '/home',
15 | 'Products' => '/products',
16 | 'Company' => '/company',
17 | 'Privacy Policy' => '/privacy-policy'
18 | );
19 |
20 | // storage of output
21 | $output = new ArrayIterator();
22 |
23 | try {
24 |
25 | // create the caching iterator of the nav array
26 | $it = new CachingIterator(new ArrayIterator($nav));
27 | foreach ($it as $name => $url) {
28 | if ($it->hasNext()) {
29 | $output->append('
' . $name . '');
30 | } else {
31 | $output->append('' . $name . '');
32 | }
33 | }
34 |
35 | // if we have values, output the unordered list
36 | if ($output->count()) {
37 | echo '' . "\n" . implode("\n", (array) $output) . "\n" . '
';
38 | }
39 |
40 | } catch (Exception $e) {
41 | die($e->getMessage());
42 | }
43 |
44 | /**
45 | * Below is the same example, but prettified in a nice, extensible class
46 | * allowing you to reuse it for nav, subnav, or any time you need to
47 | * determine the last element of an array.
48 | */
49 | class NavBuilder extends CachingIterator {
50 |
51 | /**
52 | * Override the current() method to modify the return value
53 | * for the given index.
54 | *
55 | * @access public
56 | * @return string
57 | */
58 | public function current()
59 | {
60 | // get the name and url of the nav item
61 | $name = parent::key();
62 | $url = parent::current();
63 |
64 | // determine if we're on the last element
65 | if ($this->hasNext()) {
66 | return '' . $name . '';
67 | } else {
68 | return '' . $name . '';
69 | }
70 | }
71 |
72 | /**
73 | * Outputs the navigation.
74 | */
75 | public function generate()
76 | {
77 | $inner = $this->getInnerIterator();
78 | var_dump(get_class_methods($inner));
79 | }
80 |
81 | }
82 |
83 | try {
84 | $it = new NavBuilder(new ArrayIterator($nav));
85 | echo $it->generate();
86 | } catch (Exception $e) {
87 | var_dump($e); die;
88 | }
--------------------------------------------------------------------------------
/directory-iterator-example/directory-iterator-recursive/file1.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/directory-iterator-recursive/file1.txt
--------------------------------------------------------------------------------
/directory-iterator-example/directory-iterator-recursive/file2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/directory-iterator-recursive/file2
--------------------------------------------------------------------------------
/directory-iterator-example/directory-iterator-recursive/file3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/directory-iterator-recursive/file3
--------------------------------------------------------------------------------
/directory-iterator-example/directory-iterator-recursive/hello-world:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/directory-iterator-recursive/hello-world
--------------------------------------------------------------------------------
/directory-iterator-example/file1.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file1.txt
--------------------------------------------------------------------------------
/directory-iterator-example/file2.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file2.php
--------------------------------------------------------------------------------
/directory-iterator-example/file2.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file2.txt
--------------------------------------------------------------------------------
/directory-iterator-example/file3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file3
--------------------------------------------------------------------------------
/directory-iterator-example/file4.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file4.txt
--------------------------------------------------------------------------------
/directory-iterator-example/file5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/file5
--------------------------------------------------------------------------------
/directory-iterator-example/second-directory/newfile.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/second-directory/newfile.php
--------------------------------------------------------------------------------
/directory-iterator-example/second-directory/third-directory/you_found_me:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/second-directory/third-directory/you_found_me
--------------------------------------------------------------------------------
/directory-iterator-example/test.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cballou/PHP-SPL-Iterator-Interface-Examples/bf04445fd0ebc8639d9cac8be7dfd6183abfa7d8/directory-iterator-example/test.php
--------------------------------------------------------------------------------
/directory-iterator-pt2.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class DirectoryUsage
18 | {
19 | /**
20 | * Recursively list the contents of a directory. Second parameter allows you
21 | * to specify whether you'd like to only return a list of directories or files.
22 | *
23 | * @param string $dir
24 | * @param string $type ['file'|'dir']
25 | * @return array
26 | */
27 | public function dirListByType($dir, $type = 'file')
28 | {
29 | $output = array();
30 |
31 | $it = new RecursiveDirectoryIterator($dir);
32 | $it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
33 | foreach ($it as $file) {
34 | if ($file->getType() == $type) {
35 | $output[] = $file->getPathname();
36 | }
37 | }
38 |
39 | return $output;
40 | }
41 |
42 | /**
43 | * Example of using SPL to clean up directories by removing specific filenames.
44 | *
45 | * @access public
46 | * @param string $directory
47 | * @param array $filter
48 | */
49 | public function cleanDir($directory, $filter = array('_vti_cnf', '_vti_private', '_vti_txt', '_private', '_themes', 'msupdate', 'vti_pvt', 'vti_script', '_vti_log', '_template','Thumbs.db'))
50 | {
51 | $it = new RecursiveDirectoryIterator($directory);
52 | $it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
53 | foreach ($it as $file) {
54 |
55 | // remove empty dirs
56 | if (sizeof($file->getSize()) == 0) {
57 | unlink($file->getPath());
58 | }
59 |
60 | // remove instances of Thumbs.db
61 | if ($file->getFileName() == 'Thumbs.db') {
62 | unlink($file->getPath() . DIRECTORY_SEPARATOR . $file->getFilename());
63 | }
64 |
65 | // if paths match filter, delete directory recursively
66 | $parts = explode(DIRECTORY_SEPARATOR, $file->getPath());
67 | if(in_array(end($parts), $filter)) {
68 | $this->deleteDir($file->getPath());
69 | }
70 |
71 | }
72 | }
73 |
74 | /**
75 | * Method to get information about all the files in a directory (recursive)
76 | *
77 | * @param string $directory
78 | * @param array $filter
79 | * @return array
80 | */
81 | public function fileInfo($directory, $filter = array('php', 'xsl', 'xml', 'htm', 'html','css'))
82 | {
83 | $count_directories = 0;
84 | $count_files = 0;
85 | $count_lines = 0;
86 | $count_bytes = 0;
87 |
88 | $it = new RecursiveDirectoryIterator($directory);
89 | $it = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST);
90 |
91 | foreach ($it as $file) {
92 | if (false === $file->isDir()) {
93 | // get the file extension
94 | $ext = $file->getExtension();
95 | if (in_array($ext, $filter)) {
96 | $count_files++;
97 | $count_bytes += $file->getSize();
98 | $count_lines += sizeof(explode("n", file_get_contents($file->getPathName())));
99 | }
100 | } else if(false === strpos($file->getPathname(), 'CVS') && $file->isDir()) {
101 | $count_directories++;
102 | }
103 | }
104 |
105 | return array(
106 | 'bytes' => $count_bytes,
107 | 'files' => $count_files,
108 | 'lines' => $count_lines,
109 | 'directories' => $count_directories
110 | );
111 | }
112 |
113 | /**
114 | * Recursively delete a directory and all subdirectories.
115 | *
116 | * @access public
117 | * @param string $dir
118 | * @return void
119 | */
120 | public function deleteDir($dir)
121 | {
122 | $it = new RecursiveDirectoryIterator($dir);
123 | $it = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST);
124 | foreach ($it as $file) {
125 | if ($file->isDir()) {
126 | rmdir($file->getPathname());
127 | } else {
128 | unlink($file->getPathname());
129 | @rmdir($dir);
130 | }
131 | }
132 | @rmdir($dir);
133 | }
134 |
135 | /**
136 | * Find a file by regex in a given directory.
137 | *
138 | * @param string $path
139 | * @param string $regex
140 | * @return array
141 | */
142 | public function fileFinder($path, $regex)
143 | {
144 | $matches = array();
145 |
146 | $fileList = new DirMatch($path, $regex);
147 | foreach ($fileList as $file) {
148 | $matches[] = $file;
149 | }
150 |
151 | return $matches;
152 | }
153 |
154 | /**
155 | * List files in a given directory.
156 | *
157 | * @param string $dir
158 | * @return array
159 | */
160 | public function fileLister($dir)
161 | {
162 | $files = array();
163 |
164 | $filtered = new DirectoryFilterDots($dir);
165 | foreach ($filtered as $file) {
166 | if ($file->isDir()) {
167 | continue;
168 | }
169 | $files[] = $file->getFilename();
170 | }
171 |
172 | return $files;
173 | }
174 |
175 | }
176 |
177 | // generate the directory path to the example dir
178 | $dir = __DIR__ . DIRECTORY_SEPARATOR . 'directory-iterator-example';
179 |
180 | // load up the class
181 | $DirectoryUsage = new DirectoryUsage();
182 |
183 | echo '==================================' . PHP_EOL;
184 | echo 'Recursively show all files in a directory.' . PHP_EOL;
185 | echo '==================================' . PHP_EOL;
186 |
187 | $files = $DirectoryUsage->dirListByType($dir, 'file');
188 | foreach ($files as $f) {
189 | echo $f . PHP_EOL;
190 | }
191 |
192 | echo '==================================' . PHP_EOL;
193 | echo 'Recursively show all directories in a directory.' . PHP_EOL;
194 | echo '==================================' . PHP_EOL;
195 |
196 | $dirs = $DirectoryUsage->dirListByType($dir, 'dir');
197 | foreach ($dirs as $d) {
198 | echo $d . PHP_EOL;
199 | }
200 |
201 | echo '==================================' . PHP_EOL;
202 | echo 'Recursively iterate over all files in a directory.' . PHP_EOL;
203 | echo '==================================' . PHP_EOL;
204 |
205 | // recursively generate a tree representation
206 | $files = new DirectoryTreeIterator($dir);
207 | foreach ($files as $f) {
208 | echo $f . PHP_EOL;
209 | }
210 |
211 | echo '==================================' . PHP_EOL;
212 | echo 'Iterate over a all files in a directory, filtering out dots.' . PHP_EOL;
213 | echo '==================================' . PHP_EOL;
214 |
215 | // recursively generate a tree representation
216 | $files = new DirectoryFilterDots($dir);
217 | foreach ($files as $f) {
218 | echo $f . PHP_EOL;
219 | }
220 |
221 | echo '==================================' . PHP_EOL;
222 | echo 'Find all files with a PHP extension.' . PHP_EOL;
223 | echo '==================================' . PHP_EOL;
224 |
225 | // filter by PHP file extension
226 | $phpFiles = new ExtensionFilter(new DirectoryIterator($dir), 'php', $whitelist=true);
227 | foreach ($phpFiles as $f) {
228 | echo $f->getPathName() . PHP_EOL;
229 | }
230 |
231 | echo '==================================' . PHP_EOL;
232 | echo 'Find all files without a PHP extension.' . PHP_EOL;
233 | echo '==================================' . PHP_EOL;
234 |
235 | // filter by PHP file extension
236 | $phpFiles = new ExtensionFilter(new DirectoryIterator($dir), 'php', $whitelist=false);
237 | foreach ($phpFiles as $f) {
238 | echo $f->getPathName() . PHP_EOL;
239 | }
--------------------------------------------------------------------------------
/directory-iterator.php:
--------------------------------------------------------------------------------
1 | isDot()) {
12 | // example of the
13 | echo $file->getRealPath() . PHP_EOL;
14 | }
15 | }
--------------------------------------------------------------------------------
/directory-iterator/directory-match.php:
--------------------------------------------------------------------------------
1 | getMessage());
23 | }
24 | }
25 |
26 | /**
27 | * Skip over elements with children, returning keys.
28 | *
29 | * @access public
30 | * @return string
31 | */
32 | public function current()
33 | {
34 | if ($this->hasChildren()) {
35 | $this->next();
36 | }
37 | return $this->getInnerIterator()->current()->getPath() . DIRECTORY_SEPARATOR . $this->key();
38 | }
39 |
40 | /**
41 | * An aggregate of the inner iterator.
42 | *
43 | * @access public
44 | * @param string $func
45 | * @param mixed $params
46 | */
47 | public function __call($func, $params)
48 | {
49 | return call_user_func_array(array($this->getSubIterator(), $func), $params);
50 | }
51 | }
--------------------------------------------------------------------------------
/directory-iterator/filter-dots.php:
--------------------------------------------------------------------------------
1 | getInnerIterator()->isDot();
28 | }
29 |
30 | /**
31 | * Override the key method to return the path name.
32 | *
33 | * @access public
34 | * @return string The current entries path name
35 | */
36 | public function key()
37 | {
38 | return $this->getInnerIterator()->getPathname();
39 | }
40 | }
--------------------------------------------------------------------------------
/directory-iterator/filter-extension.php:
--------------------------------------------------------------------------------
1 | _it = $it;
21 | $this->_ext = $ext;
22 | $this->_whitelisted = $whitelisted;
23 | }
24 |
25 | /**
26 | * Given the current iterator position, check the filename against
27 | * the extension and filter accordingly.
28 | *
29 | * @access public
30 | * @return bool
31 | */
32 | public function accept()
33 | {
34 | $return = true;
35 |
36 | // skip dots
37 | if ($this->_it->isDot()) return false;
38 |
39 | // pop off the extension for non-directories and try to match
40 | if (!$this->_it->isDir()) {
41 | $ext = $this->_it->getExtension();
42 |
43 | if ($this->_whitelisted) {
44 | if (is_array($this->_ext)) {
45 | $return = in_array($ext, $this->_ext);
46 | } else {
47 | $return = $ext === $this->_ext;
48 | }
49 | } else {
50 | if (is_array($this->_ext)) {
51 | $return = !in_array($ext, $this->_ext);
52 | } else {
53 | $return = $ext !== $this->_ext;
54 | }
55 | }
56 | }
57 |
58 | return $return;
59 | }
60 | }
--------------------------------------------------------------------------------
/directory-iterator/filter-key.php:
--------------------------------------------------------------------------------
1 | _regex = $regex;
20 | }
21 |
22 | /**
23 | * Provide the required accept() method for filtering keys by
24 | * a regular expression.
25 | *
26 | * @access public
27 | * @return int|bool
28 | */
29 | public function accept()
30 | {
31 | return preg_match($this->_regex, $this->getInnerIterator()->key());
32 | }
33 |
34 | /**
35 | * Override the cloning method.
36 | *
37 | * @access protected
38 | * @return bool
39 | */
40 | protected function __clone() {
41 | return false;
42 | }
43 | }
--------------------------------------------------------------------------------
/filter-iterator.php:
--------------------------------------------------------------------------------
1 | _filterKey = $filterKey;
28 | $this->_filterVal = $filterVal;
29 | }
30 |
31 | /**
32 | * The accept method is required, as FilterExample
33 | * extends FilterIterator with abstract method accept().
34 | *
35 | * @access public
36 | * @accept Only allow values that are not ___
37 | * @return string
38 | */
39 | public function accept()
40 | {
41 | $object = $this->getInnerIterator()->current();
42 | // base case
43 | if (!isset($object[$this->_filterKey])) return true;
44 | // if the key and value match the filter
45 | if (strcasecmp($object[$this->_filterKey], $this->_filterVal) == 0) {
46 | return false;
47 | }
48 | return true;
49 | }
50 | }
51 |
52 | // load up an append iterator
53 | $it = new AppendIterator();
54 |
55 | // create some example users as ArrayIterators
56 | $user1 = new ArrayIterator(array('id' => 1, 'name' => 'George'));
57 | $user2 = new ArrayIterator(array('id' => 2, 'name' => 'John'));
58 | $user3 = new ArrayIterator(array('id' => 3, 'name' => 'Eric'));
59 | $user4 = new ArrayIterator(array('id' => 4, 'name' => 'Jason'));
60 | $user5 = new ArrayIterator(array('id' => 5, 'name' => 'Emanuel'));
61 |
62 | // filter and append the ArrayIterators
63 | $it->append(new ObjectFilter($user1, 'name', 'Eric'));
64 | $it->append(new ObjectFilter($user2, 'name', 'Eric'));
65 | $it->append(new ObjectFilter($user3, 'name', 'Eric'));
66 | $it->append(new ObjectFilter($user4, 'name', 'Eric'));
67 | $it->append(new ObjectFilter($user5, 'name', 'Eric'));
68 |
69 | // show the example filtered output
70 | foreach($it as $key => $val) {
71 | echo $key . ' = ' . $val . PHP_EOL;
72 | }
73 |
74 |
75 | /**
76 | * This is the same example, but utilising ArrayObject
77 | * instead of AppendIterator and ArrayIterator.
78 | */
79 | $users = array(
80 | array('id' => 1, 'name' => 'George'),
81 | array('id' => 2, 'name' => 'John'),
82 | array('id' => 3, 'name' => 'Eric'),
83 | array('id' => 4, 'name' => 'Jason'),
84 | array('id' => 5, 'name' => 'Emanuel')
85 | );
86 |
87 | // convert users to ArrayObject
88 | $users = new ArrayObject($users);
89 |
90 | // filter out all user's with the name "John"
91 | $it = new ObjectFilter($users->getIterator(), 'name', 'john');
--------------------------------------------------------------------------------
/iterator-callback.php:
--------------------------------------------------------------------------------
1 | key()] = $prefix . '_' . $it->current();
14 | echo PHP_EOL;
15 | return true;
16 | }
17 |
18 | // example array of table names to prefix
19 | $array = array('users', 'roles', 'users_roles', 'users_profile');
20 |
21 | try {
22 |
23 | // apply the callback function to the iterator
24 | $it = new ArrayIterator($array);
25 | $prefix = 'example';
26 | iterator_apply($it, 'addDbPrefix', array($it, $prefix));
27 |
28 | } catch(Exception $e) {
29 | die($e->getMessage());
30 | }
31 |
--------------------------------------------------------------------------------
/limit-iterator.php:
--------------------------------------------------------------------------------
1 | _it = $it;
37 | $this->_count = $it->count();
38 |
39 | $this->setCurrentPage($page);
40 | $this->setItemsPerPage($limit);
41 | }
42 |
43 | /**
44 | * Set the number of items to display per page.
45 | *
46 | * @access public
47 | * @param int $count
48 | */
49 | public function setItemsPerPage($count = 10)
50 | {
51 | $this->_itemsPerPage = (int) $count;
52 | $this->_totalPages = ($this->_count > $this->_itemsPerPage) ? ceil($this->_count / $this->_itemsPerPage) : 1;
53 | }
54 |
55 | /**
56 | * Set the current page (offset).
57 | *
58 | * @access public
59 | * @param int $page
60 | */
61 | public function setCurrentPage($page = 1)
62 | {
63 | $this->_currentPage = (int) $page;
64 | }
65 |
66 | /**
67 | * Returns the current page.
68 | *
69 | * @access public
70 | * @return int
71 | */
72 | public function getCurrentPage()
73 | {
74 | return $this->_currentPage;
75 | }
76 |
77 | /**
78 | * Determines if another page exists.
79 | *
80 | * @access public
81 | * @return bool
82 | */
83 | public function hasNextPage()
84 | {
85 | return $this->_currentPage < $this->_totalPages;
86 | }
87 |
88 | /**
89 | * Determines if a previous page exists.
90 | *
91 | * @access public
92 | * @return bool
93 | */
94 | public function hasPreviousPage()
95 | {
96 | return $this->_currentPage > 1;
97 | }
98 |
99 | /**
100 | * Returns (fake render) the items matching the specific requirements.
101 | *
102 | * @access public
103 | * @param mixed $page
104 | * @param mixed $limit
105 | * @return mixed
106 | */
107 | public function render($page = NULL, $limit = NULL)
108 | {
109 | if (!empty($page)) {
110 | $this->setCurrentPage($page);
111 | }
112 |
113 | if (!empty($limit)) {
114 | $this->setItemsPerPage($limit);
115 | }
116 |
117 | // quickly calculate the offset based on the page
118 | if ($page > 0) $page -= 1;
119 | $offset = $page * $this->_itemsPerPage;
120 |
121 | // return the limit iterator
122 | return new LimitIterator($this->_it, $offset, $this->_itemsPerPage);
123 | }
124 |
125 | }
126 |
127 | // generate an example of page items to iterate over
128 | $items = array(
129 | array('id' => 1, 'name' => 'Item 1', 'desc' => 'Description', 'price' => 4.99),
130 | array('id' => 2, 'name' => 'Item 2', 'desc' => 'Description', 'price' => 4.99),
131 | array('id' => 3, 'name' => 'Item 3', 'desc' => 'Description', 'price' => 4.99),
132 | array('id' => 4, 'name' => 'Item 4', 'desc' => 'Description', 'price' => 4.99),
133 | array('id' => 5, 'name' => 'Item 5', 'desc' => 'Description', 'price' => 4.99),
134 | array('id' => 6, 'name' => 'Item 6', 'desc' => 'Description', 'price' => 4.99),
135 | array('id' => 7, 'name' => 'Item 7', 'desc' => 'Description', 'price' => 4.99),
136 | array('id' => 8, 'name' => 'Item 8', 'desc' => 'Description', 'price' => 4.99),
137 | array('id' => 9, 'name' => 'Item 9', 'desc' => 'Description', 'price' => 4.99),
138 | array('id' => 10, 'name' => 'Item 10', 'desc' => 'Description', 'price' => 4.99),
139 | array('id' => 11, 'name' => 'Item 11', 'desc' => 'Description', 'price' => 4.99),
140 | array('id' => 12, 'name' => 'Item 12', 'desc' => 'Description', 'price' => 4.99),
141 | array('id' => 13, 'name' => 'Item 13', 'desc' => 'Description', 'price' => 4.99),
142 | array('id' => 14, 'name' => 'Item 14', 'desc' => 'Description', 'price' => 4.99),
143 | array('id' => 15, 'name' => 'Item 15', 'desc' => 'Description', 'price' => 4.99),
144 | array('id' => 16, 'name' => 'Item 16', 'desc' => 'Description', 'price' => 4.99),
145 | array('id' => 17, 'name' => 'Item 17', 'desc' => 'Description', 'price' => 4.99),
146 | array('id' => 18, 'name' => 'Item 18', 'desc' => 'Description', 'price' => 4.99),
147 | array('id' => 19, 'name' => 'Item 19', 'desc' => 'Description', 'price' => 4.99),
148 | array('id' => 20, 'name' => 'Item 20', 'desc' => 'Description', 'price' => 4.99),
149 | array('id' => 21, 'name' => 'Item 21', 'desc' => 'Description', 'price' => 4.99)
150 | );
151 |
152 | // load the paginator
153 | $Paginator = new Paginator(new ArrayIterator($items));
154 |
155 | // displays the initial set (page 1, limit 10)
156 | $results = $Paginator->render();
157 | foreach ($results as $r) {
158 | var_dump($r);
159 | }
160 |
161 | // check for another page
162 | if ($Paginator->hasNextPage()) {
163 | echo 'DISPLAYING THE NEXT SET OF RESULTS AS AN EXAMPLE' . PHP_EOL;
164 | // displays the next page results as an example
165 | $results = $Paginator->render($Paginator->getCurrentPage() + 1);
166 | foreach ($results as $r) {
167 | var_dump($r);
168 | }
169 | }
--------------------------------------------------------------------------------
/observable.php:
--------------------------------------------------------------------------------
1 | containsObserver($observer)) {
47 | $this->_observers[] = $observer;
48 | }
49 | }
50 |
51 | /**
52 | * Deletes an observer from the set of observers contained within
53 | * this particular observable.
54 | *
55 | * @access public
56 | * @param Observer $observer the observer to be deleted.
57 | * @return void
58 | */
59 | public function deleteObserver(SplObserver $observer)
60 | {
61 | if ($this->containsObserver($observer)) {
62 | $this->observers = array_diff($this->_observers, array($observer));
63 | }
64 | }
65 |
66 | /**
67 | * Clears the observer list so that this object no longer has any observers.
68 | *
69 | * @access public
70 | * @return void
71 | */
72 | public function deleteObservers()
73 | {
74 | unset($this->_observers);
75 | $this->_observers = array();
76 | }
77 |
78 | /**
79 | * If this object has changed, as indicated by the hasChanged method, then
80 | * notify all of its observers and then call the clearChanged method to
81 | * indicate that this object has no longer changed.
82 | *
83 | * @access public
84 | * @return void
85 | */
86 | public function notifyObservers()
87 | {
88 | foreach ($this->_observers as $observer) {
89 | $observer->update($this);
90 | }
91 | }
92 |
93 | /**
94 | * Returns the number of observers of this Observable object.
95 | *
96 | * @access public
97 | * @return int the number of observers of this object.
98 | */
99 | public function countObservers()
100 | {
101 | return count($this->_observers);
102 | }
103 |
104 | /**
105 | * Check if observer already exists in the list.
106 | *
107 | * @param SplObserver $observer
108 | * @return bool
109 | */
110 | public function containsObserver(SplObserver $observer)
111 | {
112 | return in_array($observer, $this->_observers);
113 | }
114 |
115 | /**
116 | * Add an observer.
117 | *
118 | * @access public
119 | * @param SplObserver $observer
120 | * @return void
121 | */
122 |
123 | public function attach(SplObserver $observer)
124 | {
125 | $this->addObserver($observer);
126 | }
127 |
128 | /**
129 | * Remove an observer.
130 | *
131 | * @access public
132 | * @param SplObserver $observer
133 | * @return void
134 | */
135 | public function detach(SplObserver $observer)
136 | {
137 | $this->deleteObserver($observer);
138 | }
139 |
140 | /**
141 | * Notify observers of a change.
142 | *
143 | * @access public
144 | * @return void
145 | */
146 | public function notify()
147 | {
148 | $this->notifyObservers();
149 | }
150 |
151 | }
152 |
153 |
154 | //============================
155 | // example usage of Observable
156 | //============================
157 |
158 | class KillBot implements SplObserver
159 | {
160 | public function update(SplSubject $subject)
161 | {
162 | echo __CLASS__ . " says kill all humans." . PHP_EOL;
163 | }
164 | }
165 |
166 | class LoveBot implements SplObserver
167 | {
168 | public function update(SplSubject $subject)
169 | {
170 | echo __CLASS__ . " says kiss all humans." . PHP_EOL;
171 | }
172 | }
173 |
174 | // load the observable (SPLSubject)
175 | $robots = new Observable();
176 |
177 | // load some observers
178 | $killbot = new KillBot();
179 | $lovebot = new LoveBot();
180 |
181 | // add the observers to the observable
182 | $robots->addObserver($killbot);
183 | $robots->addObserver($lovebot);
184 |
185 | // notify the observers of an event
186 | $robots->notify();
187 |
188 | /*
189 | Observers output:
190 |
191 | KillBot says kill all humans
192 | LoveBot says kiss all humans
193 | */
194 |
--------------------------------------------------------------------------------
/observer-exception-handler.php:
--------------------------------------------------------------------------------
1 | _exception;
44 | }
45 |
46 | /**
47 | * Attaches an SplObserver to the ExceptionHandler to be notified when an
48 | * uncaught Exception is thrown.
49 | *
50 | * @access public
51 | * @param SplObserver The observer to attach
52 | * @return void
53 | */
54 | public function attach(SplObserver $obs)
55 | {
56 | $id = spl_object_hash($obs);
57 | $this->_observers[$id] = $obs;
58 | }
59 |
60 | /**
61 | * Detaches the SplObserver from the ExceptionHandler, so it will no longer
62 | * be notified when an uncaught Exception is thrown.
63 | *
64 | * @access public
65 | * @param SplObserver The observer to detach
66 | * @return void
67 | */
68 | public function detach(SplObserver $obs)
69 | {
70 | $id = spl_object_hash($obs);
71 | unset($this->_observers[$id]);
72 | }
73 |
74 | /**
75 | * Notify all observers of the uncaught Exception so they can handle it as
76 | * needed.
77 | *
78 | * @access public
79 | * @return void
80 | */
81 | public function notify()
82 | {
83 | foreach($this->_observers as $obs) {
84 | $obs->update($this);
85 | }
86 | }
87 |
88 | /**
89 | * This is the method that should be set as the default Exception handler by
90 | * the calling code.
91 | *
92 | * @access public
93 | * @return void
94 | */
95 | public function handle(Exception $e)
96 | {
97 | $this->_exception = $e;
98 | $this->notify();
99 | }
100 |
101 | }
102 |
103 | /**
104 | * The Logger exception handler is responsible for logging uncaught
105 | * exceptions to a file for debugging. It is an extension of what
106 | * would be your actual Logger class.
107 | */
108 | class ExceptionLogger extends Logger implements SplObserver
109 | {
110 | /**
111 | * Update the error_log with information about the Exception.
112 | *
113 | * @param SplSubject $subject The ExceptionHandler
114 | * @return bool
115 | */
116 | public function update(SplSubject $subject)
117 | {
118 | $exception = $subject->getException();
119 |
120 | $output = 'File: ' . $exception->getFile() . PHP_EOL;
121 | $output .= 'Line: ' . $exception->getLine() . PHP_EOL;
122 | $output .= 'Message: ' . PHP_EOL . $exception->getMessage() . PHP_EOL;
123 | $output .= 'Stack Trace:' . PHP_EOL . $exception->getTraceAsString() . PHP_EOL;
124 |
125 | echo "\n\nThe following message was sent to your default PHP error log:\n\n";
126 | echo $output;
127 |
128 | return error_log($output);
129 | }
130 | }
131 |
132 | /**
133 | * The Mailer exception handler is responsible for mailing uncaught
134 | * exceptions to an administrator for notifications. It is an extension
135 | * of what would be your actual Mailer class.
136 | */
137 | class ExceptionMailer extends Mailer implements SplObserver
138 | {
139 |
140 | /**
141 | * Mail the sysadmin with Exception information.
142 | *
143 | * @param SplSubject $subject The ExceptionHandler
144 | * @return bool
145 | */
146 | public function update(SplSubject $subject)
147 | {
148 | $exception = $subject->getException();
149 |
150 | // perhaps emailer also would like to know the server in question
151 | $output = 'Server: ' . $_SERVER['HOSTNAME'] . PHP_EOL;
152 | $output .= 'File: ' . $exception->getFile() . PHP_EOL;
153 | $output .= 'Line: ' . $exception->getLine() . PHP_EOL;
154 | $output .= 'Message: ' . PHP_EOL . $exception->getMessage() . PHP_EOL;
155 | $output .= 'Stack Trace:' . PHP_EOL . $exception->getTraceAsString() . PHP_EOL;
156 |
157 | $headers = 'From: webmaster@yourdomain.com' . "\r\n" .
158 | 'Reply-To: webmaster@yourdomain.com' . "\r\n" .
159 | 'X-Mailer: PHP/' . phpversion();
160 |
161 | echo "\n\nThe following email (would be) sent to your webmaster@yourdomain.com:\n\n";
162 | echo $output;
163 |
164 | //return mail('webmaster@yourdomain.com', 'Exception Thrown', $output, $headers);
165 | }
166 |
167 | }
168 |
169 | /**
170 | * Assume this Mailer class is your actual mailer class (i.e. SwiftMailer).
171 | */
172 | class Mailer { }
173 |
174 | /**
175 | * Assume this Logger class is your actual logger class.
176 | */
177 | class Logger { }
178 |
179 | //====================================
180 | // BELOW THIS LINE RUNS THE ABOVE CODE
181 | //====================================
182 |
183 | // Create the ExceptionHandler
184 | $handler = new ExceptionHandler();
185 |
186 | // Attach an Exception Logger and Mailer
187 | $handler->attach(new ExceptionLogger());
188 | $handler->attach(new ExceptionMailer());
189 |
190 | // Set ExceptionHandler::handle() as the default
191 | set_exception_handler(array($handler, 'handle'));
192 |
193 | // throw an exception for handling
194 | throw new Exception("This is a test of the emergency broadcast system\n", 0);
195 |
--------------------------------------------------------------------------------
/observer-subject-events.php:
--------------------------------------------------------------------------------
1 | _events);
44 | }
45 |
46 | /**
47 | * Add a new event by name.
48 | *
49 | * @access public
50 | * @param string $name
51 | * @param mixed $triggersMethod
52 | * @return Event
53 | */
54 | public function add($name, $triggersMethod = NULL)
55 | {
56 | if (!isset($this->_events[$name])) {
57 | $this->_events[$name] = new Event($triggersMethod);
58 | }
59 | return $this->_events[$name];
60 | }
61 |
62 | /**
63 | * Retrieve an event by name. If one does not exist, it will be created
64 | * on the fly.
65 | *
66 | * @access public
67 | * @param string $name
68 | * @return Event
69 | */
70 | public function get($name)
71 | {
72 | if (!isset($this->_events[$name])) {
73 | return $this->add($name);
74 | }
75 | return $this->_events[$name];
76 | }
77 |
78 | /**
79 | * Retrieves all events.
80 | *
81 | * @access public
82 | * @return array
83 | */
84 | public function getAll()
85 | {
86 | return $this->_events;
87 | }
88 |
89 | /**
90 | * Trigger an event. Returns the event for monitoring status.
91 | *
92 | * @access public
93 | * @param string $name
94 | * @param mixed $data The data to pass to the triggered event(s)
95 | * @return void
96 | */
97 | public function trigger($name, $data)
98 | {
99 | $this->get($name)->notify($data);
100 | }
101 |
102 | /**
103 | * Remove an event by name.
104 | *
105 | * @access public
106 | * @param string $name
107 | * @return bool
108 | */
109 | public function remove($name)
110 | {
111 | if (isset($this->_events[$name])) {
112 | unset($this->_events[$name]);
113 | return true;
114 | }
115 | return false;
116 | }
117 |
118 | /**
119 | * Retrieve the names of all current events.
120 | *
121 | * @access public
122 | * @return array
123 | */
124 | public function getNames()
125 | {
126 | return array_keys($this->_events);
127 | }
128 |
129 | /**
130 | * Magic __get method for the lazy who don't wish to use the
131 | * add() or get() methods. It will add an event if it doesn't exist,
132 | * or simply return an existing event.
133 | *
134 | * @access public
135 | * @return Event
136 | */
137 | public function __get($name)
138 | {
139 | return $this->add($name);
140 | }
141 |
142 | }
143 |
144 | /**
145 | * Attach event handlers to an event to be notified
146 | * @author Thomas RAMBAUD
147 | * @version 1.0
148 | * @access public
149 | */
150 | class Event implements SplSubject {
151 |
152 | // stores all attached observers
153 | private $_observers;
154 |
155 | /**
156 | * Default constructor to initialize the observers.
157 | *
158 | * @access public
159 | * @return void
160 | */
161 | public function __construct()
162 | {
163 | $this->_observers = new SplObjectStorage();
164 | }
165 |
166 | /**
167 | * Wrapper for the attach method, allowing for the addition
168 | * of a method name to call within the observer.
169 | *
170 | * @access public
171 | * @param SplObserver $event
172 | * @param mixed $triggersMethod
173 | * @return Event
174 | */
175 | public function bind(SplObserver $event, $triggersMethod = NULL)
176 | {
177 | $this->_observers->attach($event, $triggersMethod);
178 | return $this;
179 | }
180 |
181 | /**
182 | * Attach a new observer for the particular event.
183 | *
184 | * @access public
185 | * @param SplObserver $event
186 | * @return Event
187 | */
188 | public function attach(SplObserver $event)
189 | {
190 | $this->_observers->attach($event);
191 | return $this;
192 | }
193 |
194 | /**
195 | * Detach an existing observer from the particular event.
196 | *
197 | * @access public
198 | * @param SplObserver $event
199 | * @return Event
200 | */
201 | public function detach(SplObserver $event)
202 | {
203 | $this->_observers->detach($event);
204 | return $this;
205 | }
206 |
207 | /**
208 | * Notify all event observers that the event was triggered.
209 | *
210 | * @access public
211 | * @param mixed &$args
212 | */
213 | public function notify(&$args = null)
214 | {
215 | $this->_observers->rewind();
216 | while ($this->_observers->valid()) {
217 | $triggersMethod = $this->_observers->getInfo();
218 | $observer = $this->_observers->current();
219 | $observer->update($this, $triggersMethod, $args);
220 |
221 | // on to the next observer for notification
222 | $this->_observers->next();
223 | }
224 | }
225 |
226 | /**
227 | * Retrieves all observers.
228 | *
229 | * @access public
230 | * @return SplObjectStorage
231 | */
232 | public function getHandlers()
233 | {
234 | return $this->_observers;
235 | }
236 |
237 | }
238 |
239 | /**
240 | * You can attach an EventListener to an event to be notified when a specific
241 | * event has occured. Although unused, you can use
242 | *
243 | * @author Thomas RAMBAUD
244 | * @version 1.0
245 | * @access public
246 | */
247 | abstract class EventListener implements SplObserver {
248 |
249 | // holds all states
250 | private $_states = array();
251 |
252 | /**
253 | * Returns all states.
254 | *
255 | * @access public
256 | * @return void
257 | */
258 | public function getStates()
259 | {
260 | return $this->_states;
261 | }
262 |
263 | /**
264 | * Adds a new state.
265 | *
266 | * @access public
267 | * @param mixed $state
268 | * @param int $stateValue
269 | * @return void
270 | */
271 | public function addState($state, $stateValue = 1)
272 | {
273 | $this->_states[$state] = $stateValue;
274 | }
275 |
276 | /**
277 | * @Removes a state.
278 | *
279 | * @access public
280 | * @param mixed $state
281 | * @return bool
282 | */
283 | public function removeState($state)
284 | {
285 | if ($this->hasState($state)){
286 | unset($this->_states[$state]);
287 | return TRUE;
288 | }
289 | return FALSE;
290 | }
291 |
292 | /**
293 | * Checks if a given state exists.
294 | *
295 | * @access public
296 | * @param mixed $state
297 | * @return bool
298 | */
299 | public function hasState($state)
300 | {
301 | return isset($this->_states[$state]);
302 | }
303 |
304 | /**
305 | * Implementation of SplObserver::update().
306 | *
307 | * @access public
308 | * @param SplSubject $subject
309 | * @param mixed $triggersMethod
310 | * @param mixed &$arg Any passed in arguments
311 | */
312 | public function update(SplSubject $subject, $triggersMethod = NULL, &$arg = NULL) {
313 | if ($triggersMethod) {
314 | if (method_exists($this, $triggersMethod)) {
315 | $this->{$triggersMethod}($arg);
316 | } else {
317 | throw new Exception('The specified event method ' . get_called_class() . '::' . $triggersMethod . ' does not exist.');
318 | }
319 | } else {
320 | throw new Exception('The specified event method ' . get_called_class() . '::' . 'update() does not exist.');
321 | }
322 | }
323 |
324 | }
325 |
326 | /**
327 | * An example of creating an email notification event that gets triggered
328 | * when a new comment is added.
329 | */
330 | class EmailNotification extends EventListener {
331 |
332 | public function notify(&$comment)
333 | {
334 | $recipients = array('dude@domain.com', 'lady@organization.org');
335 | foreach ($recipients as $email) {
336 | echo 'Notifying recipient ' . $email . PHP_EOL;
337 | echo 'Comment: ' . print_r($comment, true) . PHP_EOL;
338 | //mail($email, 'Comment added', $comment['body']);
339 | }
340 | }
341 |
342 | }
343 |
344 | /**
345 | * An example of creating a new comment logger that gets triggered when a
346 | * new comment is added.
347 | */
348 | class CommentLogger extends EventListener {
349 |
350 | public function comment(&$comment)
351 | {
352 | echo 'Logging the comment:' . PHP_EOL;
353 | echo print_r($comment, true) . PHP_EOL;
354 | //error_log('notice', $comment)
355 | }
356 |
357 | }
358 |
359 | //===================================================
360 | // EXAMPLE USAGE OF THE ABOVE CLASSES BELOW THIS LINE
361 | //===================================================
362 |
363 | /**
364 | * Quick example function of adding a comment.
365 | */
366 | function add_comment($comment_info, EventDispatcher $EventDispatcher)
367 | {
368 | // insert the comment into the database
369 | $sql = sprintf('INSERT INTO comments SET created_by = %d, comment = %s, created_ts = %s',
370 | $comment_info['created_by'],
371 | '"' . mysql_real_escape_string($comment_info['comment']) . '"',
372 | '"' . time() . '"');
373 |
374 | // myqsl_query($sql);
375 |
376 | // notify any event listeners of onCommentAdded
377 | $EventDispatcher->onCommentAdded->notify($comment_info);
378 | }
379 |
380 | // load up an instance of the event handler
381 | $EventDispatcher = new EventDispatcher();
382 |
383 | // watch for comment being added and attach notification and logging
384 | $EventDispatcher->onCommentAdded->bind(new EmailNotification(), 'notify');
385 | $EventDispatcher->onCommentAdded->bind(new CommentLogger(), 'comment');
386 |
387 | // trigger the bound events for add_comment
388 | add_comment(
389 | array(
390 | 'created_by' => 1,
391 | 'comment' => 'Lorem ipsum dolor sir amet.'
392 | ),
393 | $EventDispatcher
394 | );
395 |
396 | /*
397 | You can perform the same thing above by doing the following:
398 |
399 | // add a new event
400 | $Events->add('onCommentAdded');
401 |
402 | // bind some event handlers to the event
403 | $Events->get('onCommentAdded')->attach(new EmailNotification());
404 | $Events->get('onCommentAdded')->attach(new CommentLogger());
405 |
406 | This avoids using the magic method __get(), which is particularly slow.
407 | It really depends on if you want to decrease readability.
408 | */
--------------------------------------------------------------------------------
/pdo-iterator.php:
--------------------------------------------------------------------------------
1 | _it = $it;
22 | $this->_dsn = $dsn;
23 | $this->_table = $table;
24 |
25 | parent::__construct($this->_it, self::LEAVES_ONLY);
26 | }
27 |
28 | /**
29 | * Generates a table header based on the metadata.
30 | *
31 | * @access public
32 | * @return string
33 | */
34 | public function getHeader()
35 | {
36 | $output = '' . PHP_EOL;
37 | $output .= '' . PHP_EOL;
38 | $output .= '';
39 |
40 | $results = $this->_dsn->query(sprintf('SHOW COLUMNS FROM %s', $this->_table));
41 | foreach ($results as $r) {
42 | $output .= '' . $r['Field'] . ' | ';
43 | }
44 |
45 | $output .= '
' . PHP_EOL;
46 | $output .= '' . PHP_EOL;
47 | $output .= '' . PHP_EOL;
48 | echo $output;
49 | }
50 |
51 | /**
52 | * Get the body.
53 | *
54 | * @access public
55 | * @return string
56 | */
57 | public function getBody()
58 | {
59 | $output = '';
60 | while ($this->valid()) {
61 | echo '' . $this->current() . ' | ';
62 | $this->next();
63 | }
64 | }
65 |
66 | /**
67 | * Generates the table footer.
68 | *
69 | * @access public
70 | * @return string
71 | */
72 | public function getFooter()
73 | {
74 | echo '
';
75 | }
76 |
77 | /**
78 | * Create a new table row.
79 | *
80 | * @access public
81 | * @return string
82 | */
83 | public function beginChildren() {
84 | echo '';
85 | }
86 |
87 | /**
88 | * Close a table row.
89 | *
90 | * @access public
91 | * @return string
92 | */
93 | public function endChildren() {
94 | echo '
' . PHP_EOL;
95 | }
96 |
97 | }
98 |
99 | try {
100 |
101 | // load the database via PDO
102 | $dsn = new PDO('mysql:dbname=testdb;host=127.0.0.1');
103 |
104 | // the result only implements Traversable
105 | $stmt = $dsn->prepare('SELECT * FROM test');
106 |
107 | // exceute the query
108 | $stmt->execute();
109 | $stmt->setFetchMode(PDO::FETCH_ASSOC);
110 |
111 | // get the results
112 | $results = $stmt->fetchAll();
113 |
114 | // generate the recursive iterator
115 | $it = new RecursiveArrayIterator($results);
116 | $TableRows = new TableRows($it, $dsn, 'test');
117 |
118 | // output the table
119 | $TableRows->getHeader();
120 | $TableRows->getBody();
121 | $TableRows->getFooter();
122 |
123 | } catch (PDOException $e) {
124 | die($e->getMessage());
125 | }
126 |
127 | /*
128 | CREATE DATABASE testdb;
129 | USE testdb;
130 |
131 | CREATE TABLE test (
132 | `id` int(11) unsigned auto_increment primary key,
133 | `name` varchar(32),
134 | `description` varchar(255),
135 | `created` int(11) unsigned
136 | );
137 |
138 | INSERT INTO test (id, name, description, created) VALUES
139 | (1, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
140 | (2, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
141 | (3, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
142 | (4, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
143 | (5, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
144 | (6, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
145 | (7, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
146 | (8, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
147 | (9, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW())),
148 | (10, 'Entry 1', 'Description', UNIX_TIMESTAMP(NOW()));
149 | */
150 |
--------------------------------------------------------------------------------
/recursive-caching-iterator.php:
--------------------------------------------------------------------------------
1 | '/home',
17 | 'Fake' => array(
18 | 'Double Fake' => array(
19 | 'Nested Double Fake' => '/fake/double/nested',
20 | 'Doubly Nested Double Fake' => '/fake/double/doubly'
21 | ),
22 | 'Triple Fake' => '/fake/tripe'
23 | ),
24 | 'Products' => array(
25 | 'Product 1' => '/products/1',
26 | 'Product 2' => '/products/2',
27 | 'Product 3' => '/products/3',
28 | 'Nested Product' => array(
29 | 'Nested 1' => '/products/nested/1',
30 | 'Nested 2' => '/products/nested/2'
31 | )
32 | ),
33 | 'Company' => '/company',
34 | 'Privacy Policy' => '/privacy-policy'
35 | );
36 |
37 | // storage of output
38 | $output = new ArrayIterator();
39 |
40 | try {
41 |
42 | // create the caching iterator of the nav array
43 | $it = new RecursiveIteratorIterator(
44 | new RecursiveCachingIterator(
45 | new RecursiveArrayIterator($nav)
46 | ),
47 | RecursiveIteratorIterator::SELF_FIRST
48 | );
49 |
50 | // child flag
51 | $depth = 0;
52 |
53 | // generate the nav
54 | foreach ($it as $name => $url) {
55 |
56 | // set the current depth
57 | $curDepth = $it->getDepth();
58 |
59 | // store the difference in depths
60 | $diff = abs($curDepth - $depth);
61 |
62 | // close previous nested levels
63 | if ($curDepth < $depth) {
64 | $output->append(str_repeat('', $diff));
65 | }
66 |
67 | // check if we have the last nav item
68 | if ($it->hasNext()) {
69 | $output->append('' . $name . '');
70 | } else {
71 | $output->append('' . $name . '');
72 | }
73 |
74 | // either add a subnav or close the list item
75 | if ($it->hasChildren()) {
76 | $output->append('');
77 | } else {
78 | $output->append('
');
79 | }
80 |
81 | // cache the depth
82 | $depth = $curDepth;
83 | }
84 |
85 | // if we have values, output the unordered list
86 | if ($output->count()) {
87 | echo '' . "\n" . implode("\n", (array) $output) . "\n" . '
';
88 | }
89 |
90 | } catch (Exception $e) {
91 | die($e->getMessage());
92 | }
93 |
94 |
95 | echo PHP_EOL . PHP_EOL . 'CLASS EXAMPLE' . PHP_EOL . PHP_EOL;
96 |
97 |
98 | /**
99 | * Below is the same example, but prettified in a nice, extensible class
100 | * allowing you to reuse it for nav, subnav, or any time you need to
101 | * determine the last element of an array.
102 | */
103 | class NavBuilder extends RecursiveIteratorIterator {
104 |
105 | // stores the previous depth
106 | private $_depth = 0;
107 |
108 | // stores the current iteration's depth
109 | private $_curDepth = 0;
110 |
111 | // store the iterator
112 | protected $_it;
113 |
114 | /**
115 | * Constructor.
116 | *
117 | * @access public
118 | * @param Traversable $it
119 | * @param int $mode
120 | * @param int $flags
121 | */
122 | public function __construct(Traversable $it, $mode = RecursiveIteratorIterator::SELF_FIRST, $flags = 0)
123 | {
124 | parent::__construct($it, $mode, $flags);
125 |
126 | // store the caching iterator
127 | $this->_it = $it;
128 | }
129 |
130 | /**
131 | * Override the return values.
132 | *
133 | * @access public
134 | */
135 | public function current()
136 | {
137 | // the return output string
138 | $output = '';
139 |
140 | // set the current depth
141 | $this->_curDepth = parent::getDepth();
142 |
143 | // store the difference in depths
144 | $diff = abs($this->_curDepth - $this->_depth);
145 |
146 | // get the name and url of the nav item
147 | $name = parent::key();
148 | $url = parent::current();
149 |
150 | // close previous nested levels
151 | if ($this->_curDepth < $this->_depth) {
152 | $output .= str_repeat('', $diff);
153 | }
154 |
155 | // check if we have the last nav item
156 | if ($this->hasNext()) {
157 | $output .= '' . $name . '';
158 | } else {
159 | $output .= '' . $name . '';
160 | }
161 |
162 | // either add a subnav or close the list item
163 | if ($this->hasChildren()) {
164 | $output .= '';
165 | } else {
166 | $output .= '
';
167 | }
168 |
169 | // cache the depth
170 | $this->_depth = $this->_curDepth;
171 |
172 | // return the output ( we could've also overridden current())
173 | return $output;
174 | }
175 |
176 | }
177 |
178 | //======
179 | // usage
180 | //======
181 |
182 | try {
183 |
184 | // generate the recursive caching iterator
185 | $it = new RecursiveCachingIterator(new RecursiveArrayIterator($nav));
186 |
187 | // build the navigation with the iterator
188 | $it = new NavBuilder($it, RecursiveIteratorIterator::SELF_FIRST);
189 |
190 | // display the resulting navigation
191 | echo '' . PHP_EOL;
192 | foreach ($it as $value) {
193 | echo $value . "\n";
194 | }
195 | echo '
' . PHP_EOL;
196 |
197 | } catch (Exception $e) {
198 | var_dump($e); die;
199 | }
--------------------------------------------------------------------------------
/recursive-directory-iterator.php:
--------------------------------------------------------------------------------
1 | isDot()) {
14 | // example of the
15 | echo $file->getRealPath() . PHP_EOL;
16 | }
17 | }
--------------------------------------------------------------------------------
/recursive-regex-iterator.php:
--------------------------------------------------------------------------------
1 | getFilename(), '.php') !== FALSE) {
28 | echo $d->getPath() . DIRECTORY_SEPARATOR . $d->getFilename() . PHP_EOL;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/regex-iterator.php:
--------------------------------------------------------------------------------
1 | replacement = '$2:$1';
19 |
20 | print_r(iterator_to_array($i));
21 | /*
22 | Array
23 | (
24 | [0] => 1:test
25 | [1] => 2:test
26 | [2] => 3:test
27 | )
28 | */
29 |
30 |
--------------------------------------------------------------------------------
/simplexml-iterator.php:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 | Phascolarctidae
13 | koala
14 | Bruce
15 |
16 |
17 |
18 |
19 | macropod
20 | kangaroo
21 | Bruce
22 |
23 |
24 |
25 |
26 | diprotodon
27 | wombat
28 | Bruce
29 |
30 |
31 |
32 |
33 | macropod
34 | wallaby
35 | Bruce
36 |
37 |
38 |
39 |
40 | dromaius
41 | emu
42 | Bruce
43 |
44 |
45 |
46 |
47 | Apteryx
48 | kiwi
49 | Troy
50 |
51 |
52 |
53 |
54 | kingfisher
55 | kookaburra
56 | Bruce
57 |
58 |
59 |
60 |
61 | monotremes
62 | platypus
63 | Bruce
64 |
65 |
66 |
67 |
68 | arachnid
69 | funnel web
70 | Bruce
71 | 8
72 |
73 |
74 |
75 | XML;
76 |
77 | try {
78 |
79 | // load the XML Iterator and iterate over it
80 | $sxi = new SimpleXMLIterator($xmlstring);
81 |
82 | // iterate over animals
83 | foreach ($sxi as $animal) {
84 | // iterate over category nodes
85 | foreach ($animal as $key => $category) {
86 | echo $category->species . PHP_EOL;
87 | }
88 | }
89 |
90 | } catch(Exception $e) {
91 | die($e->getMessage());
92 | }
93 |
94 | echo '===================================' . PHP_EOL;
95 | echo 'Finding all species with xpath' . PHP_EOL;
96 | echo '===================================' . PHP_EOL;
97 |
98 | // which can also be re-written for optimization
99 | try {
100 |
101 | // load the XML Iterator and iterate over it
102 | $sxi = new SimpleXMLIterator($xmlstring);
103 |
104 | // use xpath
105 | $foo = $sxi->xpath('animal/category/species');
106 | foreach ($foo as $k => $v) {
107 | echo $v . PHP_EOL;
108 | }
109 |
110 | } catch(Exception $e) {
111 | die($e->getMessage());
112 | }
--------------------------------------------------------------------------------