[PHP] Iterators.
Hi. OK. I'm stuck. I just can't work this out. I like SPL. I like the re-usability. It seems right. But I just can't work it out. I want to read through a file system, looking for files of a particular type. I want to ignore and not traverse any folder with a specific name anywhere in the directory tree. I want to examine the contents of the file with a set of regular expressions and call a closure for each match for each regex which will replace and replace the file with the amended one. I want to get a list of the files altered along with which regex and the number of changes. The part I'm really stuck on is working out what elements of the SPL fit my issue the best and what bits I have to implement myself, with regard to the file system iteration and filtering. The tree is pretty large - just over 5,000 files with 5,700 directories. The deepest file is 12 levels down. Now I know someone could supply a solution not using the SPL. I've got one of those. But trying to use the SPL just seems to awkward. Too many choices. Too many things with the same name Iterator, RecursiveIterator, RecusiverIteratorIterator. An Iterator suggests that it can work on a simple array ($argv for example). A non SPL variant would be foreach(). A RecursiveIterator suggests it can iterator recursively on nested data (a file system for example). Using a function which uses scandir() and calls itself for a directory would look like a recursive iterator. So what does a RecursiveIteratorIterator do? Documentation says Can be used to iterate through recursive iterators.. But that sounds daft. The RecursiveIterator is the handling the parent/child/tree navigation (isn't it - if not why not?) The name really doesn't help me to understand what's going on or what its for. Is there any place that can describe the SPL in a different way. I know it's probably just me, but it really seems like I'm only just scratching the surface. And not really getting anywhere. -- Richard Quadling Twitter : EE : Zend @RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Iterators.
On Fri, Dec 3, 2010 at 08:09, Richard Quadling rquadl...@gmail.com wrote: Now I know someone could supply a solution not using the SPL. I've got one of those. But trying to use the SPL just seems to awkward. Too many choices. Too many things with the same name I put an example up on the list this week, actually. Had you seen it? If not, or if you can't find it in the archives, let me know (even on chat) and I'll repost it. -- /Daniel P. Brown Dedicated Servers, Cloud and Cloud Hybrid Solutions, VPS, Hosting (866-) 725-4321 http://www.parasane.net/ -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Iterators.
On Fri, Dec 3, 2010 at 6:09 AM, Richard Quadling rquadl...@gmail.comwrote: Hi. OK. I'm stuck. I just can't work this out. I like SPL. I like the re-usability. It seems right. But I just can't work it out. I want to read through a file system, looking for files of a particular type. I want to ignore and not traverse any folder with a specific name anywhere in the directory tree. I want to examine the contents of the file with a set of regular expressions and call a closure for each match for each regex which will replace and replace the file with the amended one. I want to get a list of the files altered along with which regex and the number of changes. That could work with DirectoryIterator, a subclass thereof, or a combination of DirectoryIterator and FilterIterator. The part I'm really stuck on is working out what elements of the SPL fit my issue the best and what bits I have to implement myself, with regard to the file system iteration and filtering. You have a few options as I mentioned above. Depends on whether you want to encapsulate the logic you're mentioning or if you just want to use it in one place. The simplest way to go is DirectoryIterator, driving the iteration via foreach, and your custom logic goes inside the body of the foreach. foreach(new DirectoryIterator('.') as $oFile) { // custom, one-off logic here // ex. skip directories w/ a given name if($oFile-isDir() $oFile-getFilename() == 'LeaveMeAlone') continue; } Issue here is the logic portion is not very re-usable. You could easily move the logic into a subclass though if you want to have re-usable logic. Most likely this will end up in the current() function, however, you may want to consider dividing up the logic between a DirectoryIterator subclass and a FilterIterator implementation. FilterIterator lends itself to the 'should I operate on this node' question, so when you're talking about looking for files of a certain type and folders of a certain name, that sounds like it should go in a FilterIterator. However, at a cursory glance, if you want to skip entire sets of children based on the name of a given directory, you'll likely need to iterate a RecursiveDirectoryIterator yourself of subclass RecursiveIteratorIterator. For the other part, w/ the closure, changing files and tracking which files have been changed, that sounds best for a DirectoryIterator subclass. And if you're planning on handling multiple directories, w/ nested children, go for a RecursiveDirectoryIterator. The tree is pretty large - just over 5,000 files with 5,700 directories. The deepest file is 12 levels down. Now I know someone could supply a solution not using the SPL. I've got one of those. But trying to use the SPL just seems to awkward. Too many choices. Too many things with the same name Iterator, RecursiveIterator, RecusiverIteratorIterator. Once you've messed with the classes for a bit, the choices become much more natural and obvious, I too was overwhelmed by the sheer number of classes when I first had a look. An Iterator suggests that it can work on a simple array ($argv for example). A non SPL variant would be foreach(). A RecursiveIterator suggests it can iterator recursively on nested data (a file system for example). Using a function which uses scandir() and calls itself for a directory would look like a recursive iterator. So what does a RecursiveIteratorIterator do? Documentation says Can be used to iterate through recursive iterators.. The RecursiveIteratorIterator is best thought as a tool to 'flatten' out a hierarchal data structure. So imagine having 1 foreach block and every node in the tree magically gets driven through it at some point. Without RecursiveIteratorIterator you have to be bothered to make calls to the hasChildren() / getChildren() methods of the RecursiveIterator, and then iterate though the child Iterators yourself. RecursiveIteratorIterator just packages that logic up in a standard way. But that sounds daft. The RecursiveIterator is the handling the parent/child/tree navigation (isn't it - if not why not?) The name really doesn't help me to understand what's going on or what its for. The docs are a little rough, but manageable after you've messed w/ the classes a bit, but I know what you mean. Is there any place that can describe the SPL in a different way. Head to the homepage of the original SPL docs, http://www.php.net/~helly/php/ext/spl/ then search for Some articles about SPL these are quite useful when getting started w/ the Iterators. I know it's probably just me, but it really seems like I'm only just scratching the surface. And not really getting anywhere. I mean, I don't know anything but am glad to help where I can. Not everyone cares for Iterators, but they're a great way to package re-usable logic and manage OO collections. Of course I doubt PHP will ever have type safe collections :O Here's a quick
Re: [PHP] Iterators.
On 3 December 2010 16:56, Nathan Nobbe quickshif...@gmail.com wrote: On Fri, Dec 3, 2010 at 6:09 AM, Richard Quadling rquadl...@gmail.com wrote: Hi. OK. I'm stuck. I just can't work this out. I like SPL. I like the re-usability. It seems right. But I just can't work it out. I want to read through a file system, looking for files of a particular type. I want to ignore and not traverse any folder with a specific name anywhere in the directory tree. I want to examine the contents of the file with a set of regular expressions and call a closure for each match for each regex which will replace and replace the file with the amended one. I want to get a list of the files altered along with which regex and the number of changes. That could work with DirectoryIterator, a subclass thereof, or a combination of DirectoryIterator and FilterIterator. The part I'm really stuck on is working out what elements of the SPL fit my issue the best and what bits I have to implement myself, with regard to the file system iteration and filtering. You have a few options as I mentioned above. Depends on whether you want to encapsulate the logic you're mentioning or if you just want to use it in one place. The simplest way to go is DirectoryIterator, driving the iteration via foreach, and your custom logic goes inside the body of the foreach. foreach(new DirectoryIterator('.') as $oFile) { // custom, one-off logic here // ex. skip directories w/ a given name if($oFile-isDir() $oFile-getFilename() == 'LeaveMeAlone') continue; } Issue here is the logic portion is not very re-usable. You could easily move the logic into a subclass though if you want to have re-usable logic. Most likely this will end up in the current() function, however, you may want to consider dividing up the logic between a DirectoryIterator subclass and a FilterIterator implementation. FilterIterator lends itself to the 'should I operate on this node' question, so when you're talking about looking for files of a certain type and folders of a certain name, that sounds like it should go in a FilterIterator. However, at a cursory glance, if you want to skip entire sets of children based on the name of a given directory, you'll likely need to iterate a RecursiveDirectoryIterator yourself of subclass RecursiveIteratorIterator. For the other part, w/ the closure, changing files and tracking which files have been changed, that sounds best for a DirectoryIterator subclass. And if you're planning on handling multiple directories, w/ nested children, go for a RecursiveDirectoryIterator. The tree is pretty large - just over 5,000 files with 5,700 directories. The deepest file is 12 levels down. Now I know someone could supply a solution not using the SPL. I've got one of those. But trying to use the SPL just seems to awkward. Too many choices. Too many things with the same name Iterator, RecursiveIterator, RecusiverIteratorIterator. Once you've messed with the classes for a bit, the choices become much more natural and obvious, I too was overwhelmed by the sheer number of classes when I first had a look. An Iterator suggests that it can work on a simple array ($argv for example). A non SPL variant would be foreach(). A RecursiveIterator suggests it can iterator recursively on nested data (a file system for example). Using a function which uses scandir() and calls itself for a directory would look like a recursive iterator. So what does a RecursiveIteratorIterator do? Documentation says Can be used to iterate through recursive iterators.. The RecursiveIteratorIterator is best thought as a tool to 'flatten' out a hierarchal data structure. So imagine having 1 foreach block and every node in the tree magically gets driven through it at some point. Without RecursiveIteratorIterator you have to be bothered to make calls to the hasChildren() / getChildren() methods of the RecursiveIterator, and then iterate though the child Iterators yourself. RecursiveIteratorIterator just packages that logic up in a standard way. But that sounds daft. The RecursiveIterator is the handling the parent/child/tree navigation (isn't it - if not why not?) The name really doesn't help me to understand what's going on or what its for. The docs are a little rough, but manageable after you've messed w/ the classes a bit, but I know what you mean. Is there any place that can describe the SPL in a different way. Head to the homepage of the original SPL docs, http://www.php.net/~helly/php/ext/spl/ then search for Some articles about SPL these are quite useful when getting started w/ the Iterators. I know it's probably just me, but it really seems like I'm only just scratching the surface. And not really getting anywhere. I mean, I don't know anything but am glad to help where I can. Not everyone cares for Iterators, but they're a great way to package re-usable logic
[PHP] Iterators
?php function A() { return new RecursiveArrayIterator(array(func_get_args())); } $a=iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6; var_dump($a); ? I'd expect this to output an array containing 2,3,4,5,6. But the result is: array(2) { [0]= int(5) [1]= int(6) } What did I miss here? Marc -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Iterators
Marc Weber wrote: ?php function A() { return new RecursiveArrayIterator(array(func_get_args())); } $a=iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6; var_dump($a); ? I'd expect this to output an array containing 2,3,4,5,6. But the result is: array(2) { [0]= int(5) [1]= int(6) } What did I miss here? how should we know with out seeing the iterator_to_array() definition? function A() { $a = func_get_args(); return new RecursiveArrayIterator(array($a)); } $a = new RecursiveIteratorIterator( A(A(2) , A(3,4), A(5,6)) ); foreach ($a as $b) echo $b; the above code outputs: 23456 - so the problem looks to be in your iterator_to_array() function. Marc --PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Iterators - seg faults again
On Mon, 12 Feb 2007 20:33:08 +0100, Jochem Maas [EMAIL PROTECTED] wrote: how should we know with out seeing the iterator_to_array() definition? iterator_to_array() function is from php. See http://de2.php.net/manual/en/function.iterator-to-array.php Here is another testcase. Why is this happening? Can you confirm this? What has to be done different? If you don't get these results (sef faults (I still want to get 2,3,4,5,6) would you mind telling me which version of php you are using? The file is t.php and its appended at the bottom (cat t.php) Thanks in advance Marc [EMAIL PROTECTED] /tmp $ php t.php == tescase is !!0!! == are the following two results the same? 1 :array(2) { [0]= int(5) [1]= int(6) } 2 :current element in my_iterator_to_arrayArray current element in my_iterator_to_array2 current element in my_iterator_to_array3 current element in my_iterator_to_array4 current element in my_iterator_to_array5 current element in my_iterator_to_array6 array(6) { [0]= array(3) { [0]= Segmentation fault [EMAIL PROTECTED] /tmp $ php t.php == tescase is !!1!! == are the following two results the same? 1 :array(2) { [0]= int(5) [1]= int(6) } 2 : foreach does print what I want (23456), why ? 2 3 4 5 6 running for each the second time results in segfault again. Why ? Segmentation fault [EMAIL PROTECTED] /tmp $ php -v PHP 5.1.6-pl6-gentoo (cli) (built: Feb 11 2007 02:37:11) Copyright (c) 1997-2006 The PHP Group Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies [EMAIL PROTECTED] /tmp $ cat t.php ?php $testcase = 1; echo ==\n; echo tescase is !!$testcase!!\n; echo ==\n; function A() { $a = func_get_args(); return new RecursiveArrayIterator(array(func_get_args())); } function my_iterator_to_array($it) { echo $it instanceof IteratorAggregate; // doesn't output anything so result is false. So I don't have to try calling getIterator manually $res = array(); while ($it-valid()){ echo current element in my_iterator_to_array, $it-current(),\n; $res[] = $it-current(); $it-next(); } return $res; } echo are the following two results the same?\n; echo 1 :; var_dump(iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6); echo 2 :; if ($testcase == 0) var_dump(my_iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6); $ri = new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6))); echo \n\nforeach does print what I want (23456), why ?\n; foreach( $ri as $v) echo $v\n; // why does the second foreach cause a segfault here? echo \n\nrunning for each the second time results in segfault again. Why ?\n; foreach( $ri as $v) echo $v\n; ? -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Iterators - seg faults again
# [EMAIL PROTECTED] / 2007-02-12 23:34:21 +0100: Why is this happening? Can you confirm this? What has to be done different? If you don't get these results (sef faults (I still want to get 2,3,4,5,6) would you mind telling me which version of php you are using? The file is t.php and its appended at the bottom (cat t.php) Thanks in advance Marc [EMAIL PROTECTED] /tmp $ php t.php == tescase is !!0!! == are the following two results the same? 1 :array(2) { [0]= int(5) [1]= int(6) } 2 :current element in my_iterator_to_arrayArray current element in my_iterator_to_array2 current element in my_iterator_to_array3 current element in my_iterator_to_array4 current element in my_iterator_to_array5 current element in my_iterator_to_array6 array(6) { [0]= array(3) { [0]= Segmentation fault [EMAIL PROTECTED] /tmp $ php t.php == tescase is !!1!! == are the following two results the same? 1 :array(2) { [0]= int(5) [1]= int(6) } 2 : foreach does print what I want (23456), why ? 2 3 4 5 6 running for each the second time results in segfault again. Why ? Segmentation fault [EMAIL PROTECTED] /tmp $ php -v PHP 5.1.6-pl6-gentoo (cli) (built: Feb 11 2007 02:37:11) Copyright (c) 1997-2006 The PHP Group Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies [EMAIL PROTECTED] /tmp $ cat t.php ?php $testcase = 1; echo ==\n; echo tescase is !!$testcase!!\n; echo ==\n; function A() { $a = func_get_args(); return new RecursiveArrayIterator(array(func_get_args())); } function my_iterator_to_array($it) { echo $it instanceof IteratorAggregate; // doesn't output anything so result is false. So I don't have to try calling getIterator manually $res = array(); while ($it-valid()){ echo current element in my_iterator_to_array, $it-current(),\n; $res[] = $it-current(); $it-next(); } return $res; } echo are the following two results the same?\n; echo 1 :; var_dump(iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6); echo 2 :; if ($testcase == 0) var_dump(my_iterator_to_array(new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6); $ri = new RecursiveIteratorIterator( A (A(2) , A (3,4), A(5,6))); echo \n\nforeach does print what I want (23456), why ?\n; foreach( $ri as $v) echo $v\n; // why does the second foreach cause a segfault here? echo \n\nrunning for each the second time results in segfault again. Why ?\n; foreach( $ri as $v) echo $v\n; I get a nice row of ducks: -rw--- 1 roman roman 2109440 Feb 12 23:09 php512.core -rw--- 1 roman roman 2043904 Feb 12 23:09 php513.core -rw--- 1 roman roman 2043904 Feb 12 23:09 php514.core -rw--- 1 roman roman 2043904 Feb 12 23:09 php515.core -rw--- 1 roman roman 2043904 Feb 12 23:09 php516.core -rw--- 1 roman roman 2203648 Feb 12 23:09 php520.core -rw--- 1 roman roman 1966080 Feb 12 23:09 php521.core This is from 5.2.1: #0 zend_std_object_get_class (object=0x7b03d0) at /usr/home/roman/install/php/php-5.2.1/Zend/zend_object_handlers.c:1044 zobj = (zend_object *) 0x8 #1 0x0046fe88 in zim_spl_Array_getChildren (ht=8061904, return_value=0x7b05e0, return_value_ptr=0x79dc78, this_ptr=0x7b03f8, return_value_used=1) at /usr/home/roman/install/php/php-5.2.1/ext/spl/spl_array.c:1386 entry = (zval **) 0x7b0268 intern = (spl_array_object *) 0x85c400 #2 0x00517a05 in zend_call_function (fci=0x7fffc870, fci_cache=0x7fffd018) at /usr/home/roman/install/php/php-5.2.1/Zend/zend_execute_API.c:984 lcname = 0x1 Address 0x1 out of bounds i = 4294952784 original_return_value = (zval **) 0x7fffc920 calling_symbol_table = (HashTable *) 0xb original_function_state_ptr = (zend_function_state *) 0x7fffd018 original_op_array = (zend_op_array *) 0x7fffc750 original_opline_ptr = (zend_op **) 0x7fffc918 current_scope = (zend_class_entry *) 0x0 calling_scope = (zend_class_entry *) 0x85c400 check_scope_or_static = (zend_class_entry *) 0x0 current_this = (zval *) 0x0 execute_data = {opline = 0x0, function_state = {function_symbol_table = 0x7afbe8, function = 0x85da00, reserved = { 0x800b646e9, 0x7aca18, 0x0, 0x7aca08}}, fbc