<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ebene7 &#187; Foreach</title>
	<atom:link href="http://blog.ebene7.com/schlagwort/foreach/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ebene7.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 Jun 2013 18:57:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>&#8220;Walkable&#8221; Iterator</title>
		<link>https://blog.ebene7.com/2012/07/31/walkable-iterator/</link>
		<comments>https://blog.ebene7.com/2012/07/31/walkable-iterator/#comments</comments>
		<pubDate>Tue, 31 Jul 2012 04:00:00 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[each]]></category>
		<category><![CDATA[Foreach]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[Schleife]]></category>
		<category><![CDATA[Visitor Pattern]]></category>
		<category><![CDATA[walk]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3499</guid>
		<description><![CDATA[In PHP haben Entwickler seit Version 5 die Möglichkeit, den Zugriff auf Datenstrukturen durch eigene oder bereits in der SPL vorhandene Iteratoren zu kontrollieren. Das ist einfach und hat sicherlich auch schon jeder einmal gemacht. Damit ist dann zumindest der &#8230; <a href="https://blog.ebene7.com/2012/07/31/walkable-iterator/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In PHP haben Entwickler seit Version 5 die Möglichkeit, den Zugriff auf Datenstrukturen durch eigene oder bereits in der <a href="http://www.php.net/~helly/php/ext/spl/" target="_blank">SPL</a> vorhandene <a href="http://blog.ebene7.com/schlagwort/iterator/">Iteratoren</a> zu kontrollieren. Das ist einfach und hat sicherlich auch schon jeder einmal gemacht.</p>
<p>Damit ist dann zumindest der eine Teil, die Datenstruktur, für sich gekapselt. Was ist aber mit dem Teil, den wir wahrscheinlich häufiger verwenden werden? Wir nutzen Iteratoren in Schleifen und machen irgendwas mit den Elementen.<span id="more-3499"></span></p>
<pre>&lt;?php
foreach($list as $key =&gt; $item) {
  $item-&gt;doSomething();
}

// oder
$values = array();
foreach($list as $key =&gt; $item) {
  $values[] = $item-&gt;getSomething();
}</pre>
<p>In verschiedenen anderen Sprachen, Java, JavaScript etc., sieht man häufig, dass dort auch die Scheifen gekapselt sind. Warum probieren wir das nicht auch mal in PHP?</p>
<p>Ich werde das Beipiel bewusst einfach halten und wie gewohnt auf einige Fehlerbehandlungen verzichten, um den Code übersichtlich zu halten.</p>
<p>Als erstes erstellen wir eine Klasse &#8220;WalkableIterator&#8221; und lassen diese von ArrayIterator erben. Die beiden Methoden &#8220;each&#8221; und &#8220;walk&#8221; bilden später unsere beiden Beispiele ab.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  public function each($method) {}
  public function walk($callback) {}
}</pre>
<p>Mit each() können wir eine bestimmte Methode auf jedem Element in unserem Iterator aufrufen. Dafür müssten hier natürlich diverse Fehlerbehandlungen rein was passieren soll, wenn das Element kein Objekt ist oder die Methode nicht existiert oder diese gar eine Exception wirft.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  public function each($method) {
    $args = func_get_args();
    $method = array_shift($args);
    foreach($this as $item) {
      call_user_func_array( array($item, $method), $args );
    }
  }
  // ...
}</pre>
<p>Das ganze ist denkbar einfach: Die Methode nimmt als ersten Pflichtparameter den Methodennamen entgegen, die auf allen Elementen aufgerufen werden soll und der Rest bleibt flexibel und wird einfach nur durchgereicht.</p>
<p>Die Implementierung von walk() wird sogar noch einfacher, da hier keine Parameter weitergegeben werden müssen. Im produktiven Einsatz müssten auch hier noch die üblichen Fehlerbehandlungen rein.</p>
<pre>&lt;?php
class WalkableIterator extends ArrayIterator {
  // ...
  public function walk($callback) {
    foreach($this as $item) {
      call_user_func( $callback, $item );
    }
  }
}</pre>
<p>Soweit, so einfach&#8230; Was können wir jetzt damit machen? Bauen wir ein kleines Beispiel.</p>
<pre>&lt;?php
// Testklasse
class Person {
  private $name;
  public function __construct($name = 'unnamed') {
    $this-&gt;setName($name);
  }
  public function getName() {
    return $this-&gt;name;
  }
  public function setName($name) {
    $this-&gt;name = $name;
  }
}

// Testarray mit Objekten befüllen
$a = array();
for($i=1; $i &lt;= 10; $i++) {
  $a[] = new Person('Person ' . $i);
}

// Iterator erstellen und Namen ausgeben
$it = new WalkableIterator($a);

foreach($it as $item) {
  echo $item-&gt;getName() . '&lt;br/&gt;';
}

// Person 1
// ...
// Person 10</pre>
<p>Wollten wir nun allen Personenobjekten einen Namen geben, so könnten wir dafür each() verwenden.</p>
<pre>&lt;?php
$it-&gt;each('setName', 'PHP-Nerd');

// PHP-Nerd
// ...
// PHP-Nerd</pre>
<p>Wollen wir unsere Personen dann vielleicht doch wieder individueller benennen, so könnten wird das mit walk() und einem <a href="http://blog.ebene7.com/schlagwort/callback/">Callback</a> machen.</p>
<pre>$callback = function(Person $person) {
  static $count = 1;
  $person-&gt;setName( $person-&gt;getName() . ' ' . $count++ );
};

$it-&gt;walk($callback);</pre>
<pre>// PHP-Nerd 1
// ...
// PHP-Nerd 10</pre>
<p>&#8220;Was bringt uns das und warum so kompliziert?&#8221;, ist in dem Zusammenhang eine oft gehörte Frage.</p>
<p>Zunächst ist die Implementierung, wie das Beispiel sicher beweist, nicht kompliziert.</p>
<p>Die Vorteile sind kürzere Aufrufe im Code, weil wir keine Schleifen mehr schreiben müssen und durch die Kapselung verbessert sich auch die Wart- und Testbarkeit. Der Code existiert nur an einer Stelle und funktioniert überall nach dem selben Muster.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2012/07/31/walkable-iterator/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Objekte und Arrays casten</title>
		<link>https://blog.ebene7.com/2010/05/18/objekte-und-arrays-casten/</link>
		<comments>https://blog.ebene7.com/2010/05/18/objekte-und-arrays-casten/#comments</comments>
		<pubDate>Tue, 18 May 2010 05:00:19 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Tipps und Tricks]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[Datenstruktur]]></category>
		<category><![CDATA[Foreach]]></category>
		<category><![CDATA[Objekt]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Scheifen]]></category>
		<category><![CDATA[Type-Cast]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=813</guid>
		<description><![CDATA[Letzte Woche fand ich den Artikel Objekte und Arrays auf phpmonkeys.de und war, ebenso wie der Autor auch, überrascht, wie einfach doch PHP zuweilen sein kann. In dem Artikel wird beschrieben, wie man Daten aus einem Array in ein Objekt &#8230; <a href="https://blog.ebene7.com/2010/05/18/objekte-und-arrays-casten/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Letzte Woche fand ich den Artikel <a href="http://www.phpmonkeys.de/2010/05/10/objekte-und-arrays/" target="_blank">Objekte und Arrays auf phpmonkeys.de</a> und war, ebenso wie der Autor auch, überrascht, wie einfach doch PHP zuweilen sein kann.</p>
<p>In dem Artikel wird beschrieben, wie man Daten aus einem Array in ein Objekt (oder auch umgekehrt) überführen kann, ohne jedesmal eine foreach-Schleife zum Kopieren herumzubauen. Der Trick ist einfach, wie auch genial: Einfach ein Typecast und gut ist.</p>
<p>Ähnliches habe ich ja schonmal in einem <a href="http://blog.ebene7.com/2010/01/08/foreach-mit-typecast/">Artikel</a> über den Umgang mit &#8220;Nicht-Arrays&#8221; und foreach-Schleifen beschrieben.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/05/18/objekte-und-arrays-casten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Es ist ein Model und es sieht gut aus &#8211; Iterator</title>
		<link>https://blog.ebene7.com/2010/05/06/es-ist-ein-model-und-es-sieht-gut-aus-iterator/</link>
		<comments>https://blog.ebene7.com/2010/05/06/es-ist-ein-model-und-es-sieht-gut-aus-iterator/#comments</comments>
		<pubDate>Thu, 06 May 2010 05:00:37 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Countable]]></category>
		<category><![CDATA[CustomLibrary]]></category>
		<category><![CDATA[Custom_Model]]></category>
		<category><![CDATA[Foreach]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[Model]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Schleife]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=430</guid>
		<description><![CDATA[Nachdem sich unsere Klasse Custom_Model während der letzten Artikel gut entwickelt hat, werden wir daran heute gleich anknüpfen und das Iterator-Interface implementieren. Was kann unser Model dann, was es vorher noch nicht konnte? Durch die Verwendung des Interfaces können wir &#8230; <a href="https://blog.ebene7.com/2010/05/06/es-ist-ein-model-und-es-sieht-gut-aus-iterator/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Nachdem sich unsere Klasse Custom_Model während der letzten Artikel gut entwickelt hat, werden wir daran heute gleich anknüpfen und das <a href="http://www.php.net/manual/de/class.iterator.php" target="_blank">Iterator-Interface</a> implementieren.</p>
<p>Was kann unser Model dann, was es vorher noch nicht konnte? Durch die Verwendung des Interfaces können wir die gespeicherten Daten in einer foreach-Schleife verarbeiten. Das kann z.B. beim erzeugen von Tabellen erforderlich sein.</p>
<p><span id="more-430"></span>Wie immer beginne ich mit einer Skizze der heutigen Erweiterungen.</p>
<pre>&lt;?php
interface Custom_Model_Interface
  extends ArrayAccess,
          Iterator,
          Countable
{
}</pre>
<p>Unser Interface Custom_Model_Interface erweitert zunächst das Iterator-Interface und auch <a href="http://www.php.net/manual/de/class.countable.php" target="_blank">Countable</a>. Dadurch lassen sich dann die Elemente des Objektes zählen und in Verbindung mit ArrayAccess auch beliebig in einer for-Schleife verarbeiten.</p>
<p>In unserer Klasse müssen wir nun die entsprechenden Methoden deklarieren.</p>
<pre>&lt;?php
class Custom_Model implements Custom_Model_Interface
{
  // ...

  public function current() {}
  public function key() {}
  public function next() {}
  public function rewind() {}
  public function valid() {}
  public function count() {}

// ...
}</pre>
<p>Jedem, der lange genug mit PHP arbeitet sollte nun was auffallen. Richtig! Wir halten unsere &#8220;Feldnamen&#8221; in einem Array und zu fast jeder Methode gibt es eine gleichnamige <a href="http://de3.php.net/manual/de/ref.array.php" target="_blank">Array-Funktion</a>.</p>
<p>Da wir aber an meistens an die Werte und nicht an die Namen der Felder wollen, müssen wir etwas tricksen.</p>
<p>Die erste Methode <code>current()</code> gibt das jeweilige Element an der Position des internen Zeigers zurück und entspricht damit der gleichnamigen Array-Funktion <a href="http://de3.php.net/manual/de/function.current.php" target="_blank"><code>current()</code></a>.</p>
<pre>public function current()
{
  return $this-&gt;_get(current($this-&gt;_keys));
}</pre>
<p>Das Gegenstück dazu stellt quasi <code>key()</code> dar, da es den Feldnamen der Position liefert.</p>
<pre>public function key()
{
  return $this-&gt;_keys[key($this-&gt;_keys)];
}</pre>
<p>Auf den ersten Blick mag diese Schreibweise vielleicht etwas verwirren, aber nur so bekommen wir den richtigen Schlüssel. <a href="http://de3.php.net/manual/de/function.key.php" target="_blank"><code>key()</code></a> gibt uns den aktuellen Schlüssel von $this-&gt;_keys zurück, wir wollen den Wert der jeweiligen Position haben.</p>
<p>Um nun in der Schleife den internen Zeiger bewegen zu können, brauchen wir <a href="http://de3.php.net/manual/de/function.next.php" target="_blank"><code>next()</code></a>.</p>
<pre>public function next()
{
  next($this-&gt;_keys);
}</pre>
<p>Wird das Objekt ein weiteres Mal mit foreach verarbeitet, so muss der interne Zeiger wieder auf die erste Position zurückgesetzt werden. Das Iterator-Interface schreibt dafür die Methode <code>rewind()</code> vor, die dann intern <a href="http://de3.php.net/manual/de/function.reset.php" target="_blank"><code>reset()</code></a> verwenden kann.</p>
<pre>public function rewind()
{
  reset($this-&gt;_keys);
}</pre>
<p>Innerhalb der Schleife wir überprüft, ob weitere Elemente vorhanden sind. Dazu wird <code>valid()</code> verwendet.</p>
<pre>public function valid()
{
  return current($this-&gt;_keys) !== false;
}</pre>
<p>Damit haben wir alles notwendige eingebaut, damit unser Model in einer foreach-Schleife ausgelesen werden kann.</p>
<pre>foreach($model as $key=&gt;$value) {
  echo $key . ' = ' . $value . '&lt;br/&gt;';
}</pre>
<p>Zuletzt gibt es dann auch noch die Methode <code>count()</code> des Countable-Interfaces, damit wir beliebig mit for-Schleifen über das Objekt iterieren können.</p>
<pre>public function count()
{
  return count($this-&gt;_keys);    
}</pre>
<p>und</p>
<pre>for($i=0; $i&lt;count($model); $i++) {
  echo $i . ' = ' . $model[$i] . '&lt;br/&gt;';
}</pre>
<p>Damit wären wir auch schon wieder am Ende. Beim nächsten Mal geht es dann weiter mit dem <a href="http://blog.ebene7.com/2010/05/07/es-ist-ein-model-und-es-sieht-gut-aus-der-observer/" target="_self">Observer-Pattern</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/05/06/es-ist-ein-model-und-es-sieht-gut-aus-iterator/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Foreach mit Typecast</title>
		<link>https://blog.ebene7.com/2010/01/08/foreach-mit-typecast/</link>
		<comments>https://blog.ebene7.com/2010/01/08/foreach-mit-typecast/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 09:00:54 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Entwicklung]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tipps und Tricks]]></category>
		<category><![CDATA[Foreach]]></category>
		<category><![CDATA[Funktion]]></category>
		<category><![CDATA[Methode]]></category>
		<category><![CDATA[Schleife]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=196</guid>
		<description><![CDATA[Hin und wieder schreiben wir Funktionen oder Methoden in PHP, die entweder eine Variable oder ein Array verarbeiten können. Oftmals findet man dann an diesen Stellen mehr oder weniger abenteuerliche Konstrukte oder unnötige rekursive Aufrufe. function machWas($values) { if (!is_array($values)) &#8230; <a href="https://blog.ebene7.com/2010/01/08/foreach-mit-typecast/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hin und wieder schreiben wir Funktionen oder Methoden in PHP, die entweder eine Variable oder ein Array verarbeiten können.</p>
<p>Oftmals findet man dann an diesen Stellen mehr oder weniger abenteuerliche Konstrukte oder unnötige <a href="http://de.wikipedia.org/wiki/Rekursion" target="_blank">rekursive</a> Aufrufe.</p>
<p><span id="more-196"></span>function machWas($values)</p>
<pre>{
  if (!is_array($values)) {
    $values = array($values);
  }

  foreach($values as $value) {
    // mach was mit $value
  }
}</pre>
<p>Stattdessen lässt sich das Beispiel aber auch wie folgt durch <a href="http://de.wikipedia.org/wiki/Typecast" target="_blank">Typecasting</a> vereinfachen.</p>
<pre>function machWas($values)
{
  foreach( (array)$values as $value) {
    // mach was mit $value
  }
}</pre>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/01/08/foreach-mit-typecast/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
