phpBuddy

Folge phpBuddy.eu auf Twitter

Ab sofort können alle Twitter-Begeisterte sich auch über die Aktivitäten von phpBuddy.eu auf Twitter informieren. Ich werde dort in unregelmäßigen Abständen über neue Artikel, Tutorials, Kurztipps, lesenswerte Forumeinträge oder schlicht interessante PHP Funktionen informieren.

Sie sind hier: Startseite Die Standard PHP Library
SPL - Die Standard PHP Library - Unser erstes Iterator-Beispiel
Beitragsseiten
SPL - Die Standard PHP Library
Unser erstes Iterator-Beispiel
Mit Verzeichnissen arbeiten
Zip-Dateien on-the-fly erstellen
Backup Basis Script
Inhalte filtern
Fazit und Schlußwort
Alle Seiten

Unser erstes Iterator-Beispiel

Das klassische Anwendungsgebiet für Iteratoren sind Arrays. Also erstellen wir ein kleines Array, leiten ein Objekt davon ab und schauen uns an was wir damit anstellen können.

 

 

 

$webtechnologien = array( "PHP", "HTML", "CSS", "MySQL", "Ruby", "JavaScript", "Flash" );
$objekt = new ArrayObject( $webtechnologien );
$zeiger = $objekt->getIterator();

Unser Array habe ich jetzt mal webtechnologien genannt, unabhängig davon ob jemand mit dem Inhalt des Array nicht einverstanden ist.
In Zeile 2 sprechen wir bereits die Klasse ArrayObject an und übergeben unser Array an diese Klasse. Das zurück gelieferte Objekt legen wir in $objekt ab. Die Klasse ArrayObject stellt zahlreiche Methoden zur Verfügung, die uns den Umgang mit einem Array erleichtert. So kann man z.B. auf zahlreiche klassische Sortier-Funktionen zugreifen, wie etwa

  • $objekt->asort()
  • $objekt->ksort()
  • $objekt->uasort()
  • $objekt->uksort()
  • $objekt->natsort()
  • $objekt->natcasesort()

Eine weitere Methode die man häufig braucht ist $objekt->count(), die einem die Anzahl der im Array befindlichen Elemente liefert. Benötigt wird das u.a. um zu wissen wie viele Schleifen-Durchläufe wir machen müssen, wie wir weiter unten noch sehen werden.
Zusammen mit der Klasse ArrayObject werden automatisch weitere Klassen geladen die ihrerseits Methoden zur Verfügung stellt. Eine dieser Klassen ist die Iterator Klasse und bildet mit ihren Methoden den Kern des Ganzen. Wer sich mal "kurz" einen kleinen Überblick verschaffen möchte in welchem Zusammenhang die Iterator Klasse zu den anderen Klassen steht, dem möchte ich dieses niedliche Diagramm an's Herz legen.

Aber schauen wir uns mal die Methoden der Iterator Klasse an:

  • current() - Beinhaltet den Wert des aktuellen Elements auf dem sich der Zeiger befindet
  • key() - Beinhaltet den Schlüssel des aktuellen Elements auf dem sich der Zeiger befindet
  • next() - Bewegt den Zeiger zum nächsten Element
  • rewind() - Bewegt den Zeiger an den Anfang des Objekts/Arrays
  • valid() - Prüft ob ein Element existiert, nachdem mit next() oder rewind() die Zeigerposition verändert wurde.

In unserem Beispiel oben ermitteln wir also mit $zeiger = $objekt->getIterator(); die Position des aktuellen Elements und übergeben diese an unseren Zeiger. Ab sofort stellt unser Zeiger ($zeiger) ein Objekt dar und wir können mit den Methoden der Klassen ArrayObject und Iterator arbeiten. Machen wir das doch einfach mal, um das etwas zu verdeutlichen:

$webtechnologien = array( "PHP", "HTML", "CSS", "MySQL", "Ruby", "JavaScript", "Flash" );
$objekt = new ArrayObject( $webtechnologien );
$zeiger = $objekt->getIterator();
 
$zeiger->rewind(); // setzt den Zeiger an die erste Position im Array
echo $zeiger->count(). "<br />"; // gibt 7 aus, da 7 Elemente in unserem Array sind
echo $zeiger->current(). "<br />"; // gibt PHP aus, da sich der Zeiger auf dem ersten Element befindet
$zeiger->next(); // bewegt den Zeiger zur nächsten Position
if ($zeiger->valid()) // prüft ob sich der Zeiger auf einem gueltigen Element befindet.
{
    echo $zeiger->key(). "<br />"; // gibt 1 aus, da sich der Zeiger auf dem 2. Element befindet 
}
 

Soweit mal die absoluten Basics. Jeder mit etwas PHP Erfahrung wird hier nicht wirklich etwas neues gesehen haben, abgesehen davon das wir ein Array objektorientiert angesprochen haben. Einzig rewind() ist vielleicht etwas neu, aber die Funktionsweise entspricht der von reset(), die hinlänglich bekannt sein sollte.

Array Iteration in der Praxis
Ist ja alles schön und gut, nur wühlt sich niemand manuell durch ein Array, deswegen sollten wir uns einmal anschauen welche Möglichkeiten wir haben ein Array mit einer Schleife auszugeben. Zu dem Zweck basteln wir uns erst mal ein neues, assoziatives Array mit einigen fiktiven Angaben und erzeugen das benötigte Objekt.

$person = array( "Vorname" => "Max",
                 "Nachname" => "Mustermann",
                 "Alter" => 39,
                 "Haarfarbe" => "Braun",
                 "Beruf" => "Rauhhaardackelzüchter" );
 
$PersonObjekt = new ArrayObject( $person );
$zeiger = $PersonObjekt->getIterator();

Soweit gibt's hier nichts neues zu sehen. Schauen wir uns jetzt an, wie wir an unsere Daten kommen.

Als foreach()-Schleife

$zeiger->rewind();
foreach ($zeiger as $schluessel => $wert)
{
    echo $schluessel. ": " .$wert. "<br />";
}

Als for()-Schleife

for ($zeiger->rewind(); $zeiger->valid(); $zeiger->next())
{
    echo $zeiger->key(). ": " .$zeiger->current(). "<br />";
}

Als while()-Schleife

$zeiger->rewind();
while ($zeiger->valid())
{
    echo $zeiger->key(). ": " .$zeiger->current(). "<br />";
    $zeiger->next();
}

Wie wir sehen bleibt sich bei foreach() alles beim alten. Kein Wunder, ist doch foreach() eigentlich die Ausgabemethode für Arrays.

Bei der for()-Schleife setzen wir den Zeiger auf den Array-Anfang ($zeiger->rewind()) zurück und übernehmen diese Position als Startwert für die Schleife. Als Bedingung benutzen wir hier $zeiger->valid() um zu prüfen ob die aktuelle Zeigerposition auf ein valides Array-Element zeigt. Mit $zeiger->next() legen wir den Intervall fest. Die Ausgabe ist dann Element-Schlüssel ($zeiger->key()) und der Element-Wert ($zeiger->current()).

Bei der while()-Schleife müssen wir etwas aufpassen, damit wir nicht durch Nachlässigkeit eine Endlosschleife produzieren. Hier wird nämlich als Bedingung geprüft: solange $zeiger->valid() True ist, führe die Schleife aus. Deswegen ist es zwingend notwendig, daß wir innerhalb der Schleifen den Zeiger immer um eine Position nach vorn schieben ($zeiger->next()), wenn die Ausgabe erfolgt ist. Nur so können wie sicherstellen das die Bedingung irgendwann False ist - nämlich dann, wenn wir an der letzten Position im Array angekommen sind und den Zeiger "über das Ende hinaus" schieben.

Alles bis hierhin war (hoffentlich) einfach nachvollziehbar. Zugegeben, einen wirklichen Durchbruch gegenüber der prozeduralen Herangehensweise ist noch nicht so ganz zu erkennen. Allerdings ist es für komplexere Aufgaben zwingend erforderlich das man den Umgang mit den Basisfunktionen beherrscht. Denn ganz gleich welche Iterator Klassen aus der SPL wir benutzen, in allen wird auf eine sehr ähnliche, bzw. identische Weise navigiert. Schauen wir uns nun ein mehr praxisbezogenes Beispiel an.