Targeting Object Iteration

I was reading this article in the SP blog and it made rethink how I do iterations. Granted , I am very new at PHP but whenever I needed to traverse an array of data from an object I just resigned myself to making that property public AND to accessit by using this syntax: $object->targetedArray.

It woks beautifully but it’s neither pretty nor secure.

So I experimented with what I learned in the article , but it seems that PHP built in iterators have one drawback: they cant take an argument, you can only iterate through the array that is hand coded or passes through as an existing property of the object, which kinda defeats the purpose


 class WebTechnologies implements IteratorAggregate  
{  
 private $tech;  
 private $names;  
     public function __construct() {  
         $this->tech = explode( ',', 'PHP,HTML,XHTML,CSS,JavaScript,XML,XSLT,ASP,C#,Ruby,Python' );  
         $this->names = explode( ',', 'Tiger,Leopard,Snow Leopard,Lion,Puma,Leopard,Panther,bengal Tiger,Linx,BobCat' );  
     }  
  public function getIterator() {  
        return new ArrayIterator($this->teach);  
   }  

}  
 $wt = new WebTechnologies();  
foreach ($wt as $n => $t) {  
   echo "<p>Technology $n: $t</p>";  
 }  

I guess I would like improve he preceding code to be able chose which array is iterated WITHOUT :having to use another property or create another object. For example, I am trying to avoid THIS solution:


 class WebTechnologies implements IteratorAggregate  
{  
[B]public $ATI;[/B]
 private $tech;  
 private $names;  
[B]     public function __construct($ati) { 
        $this->ATI=$ati; [/B]
         $this->tech = explode( ',', 'PHP,HTML,XHTML,CSS,JavaScript,XML,XSLT,ASP,C#,Ruby,Python' );  
         $this->names = explode( ',', 'Tiger,Leopard,Snow Leopard,Lion,Puma,Leopard,Panther,bengal Tiger,Linx,BobCat' );  
     }  
  public function getIterator() {  
[B]        return new ArrayIterator($this->$this->ATI);  [/B]
   }  

}  
[B] $wt = new WebTechnologies("name");  // am trying to avoid passing this info to the construct here
 // I am trying to avoid  this well , $wt->ATI="names";[/B]
foreach ($wt as $n => $t) {  
   echo "<p>Technology $n: $t</p>";  
 }  

Any insight would be greatly appreciated.

Since you don’t want to use a constructor parameter, or an object argument to determine which array is used, what other ways are there for the object to determine which array you want to use?

It’s not that I dont want to, so much as that it seems to negate the gains of using IteratorAggregate ( tho maybe I am not understanding it correctly).

for example let say I have object which contains contains THREE organized arrays of info ( or 3 propierties… whcih are arrays)

at any point I may want to access ONE of these three properties. I seems convoluted to create subclasses and/or separate instances so that I can iterate through each array. That is no gain.

ALTERNATIVELY, if i have to access a fiction to update the property to be iterated ($wt->ATI=“names”, for example) then there is not much difference (other than not using a public foo , than simply doing this: foreach ($obj->names as $n => $t) {…}

My appeal to the interface functions is that they are PRIVATE , READY , and give CUSTOM ACCESS. But they only seem to be private.

I guess I could just ask is there a way (w/o using the aforementioned techniques) send an argument to any iterator functions?

public function getIterator($arg) {
return new ArrayIterator($this->$arg);
}

foreach ($wt->getIterator(“name”) as $n => $t) { // or something like that
echo “<p>Technology $n: $t</p>”;
}
or is this just wishful thinking.

As long as am asking…
I notice that the iterators have a next() method, but I cant find a prev()… is this correct?

So that we’re on the same page about this, here’s the documentation page for ArrayIterator and [url=“http://php.net/manual/en/iteratoraggregate.getiterator.php”]getIterator

You’ll see from the getIterator documentation page that it’s defined as having no parameters.

That’s right. There’s a rewind, seek, but no prev. To easily go in reverse, you would reverse-sort the array and then process it as per normal.

That’s right. There’s a rewind, seek, but no prev. To easily go in reverse, you would reverse-sort the array and then process it as per normal.

I was hoping more along the line of adding the functionality of a “CD Player” so if you reached a marker and wanted to go back one, or any nu7mber of steps you could.

And I am REALLY new to using these classes. my understanding is getIterator is for objects , and yes i didn’t think it had parameters, but since it seemed so handy if it had I thought might have been my oversight:

ArrayIterator is for processing arrays… I just brought it up because since the end goal is to process ojbect properties that happened to be arrays, I thought it maybe a more common practice to somehow pass them onto ArrayIterator … but again I am only an egg. :slight_smile:

In that case you would need to get the current , decide if you can safely decrement it, then [url=“http://www.php.net/manual/en/arrayiterator.seek.php”]seek to the updated key index.

The purpose of getIterator is to allow an object to be accessed and treated as if it were an array. So unfortunately, pretty much all of the rules for arrays apply.

If your object is to be used for a certain commonly understood purpose, there are a certain number of design patterns that can help to reduce the number of complications that are involved in the design.

Here’s something interesting though. It’s a MultipleIterator class that allows you to attach multiple array instances. If you have two arrays, for example, it will return an array of two values, one from the first array, and one from the second.

MultipleIterator for PHP

Thanks, Paul_W.
I need to do a bit more experimenting, but i think I follow now.