Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
 
 
 

PHP ArrayObject: Arrays als Objekte nutzen und erweitern

Sie befinden sich: Home > Php Tutorial > PHP ArrayObject: Arrays als...

PHP ArrayObject: Arrays als Objekte nutzen und erweitern
Eintrag am:
07.08.2026
Hits / Besucher:
4
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Ein Array in PHP kann viel, aber es kann nichts von allein. Es prüft keine Werte, es kennt keine Regeln, und wer eine Liste kapseln will, landet schnell bei einer Klasse mit einem öffentlichen Array darin, in das dann doch wieder jeder hineinschreibt. Genau an dieser Stelle setzt PHP ArrayObject an: eine Klasse aus der Standardbibliothek, die sich nach aussen wie ein Array anfühlt und innen eigene Logik mitbringt.

Illustration zum Tutorial: PHP ArrayObject: Arrays als Objekte nutzen und erweitern

Bevor der erste Code kommt, lohnt die ehrliche Frage, wann sich der Umweg überhaupt rechnet.

Wozu PHP ArrayObject, wenn es Arrays gibt?

Die kurze Antwort: meistens brauchst du es nicht. Ein normales Array ist schneller, sparsamer und jedem Entwickler sofort vertraut. Wer eine Liste von Namen durchläuft, hat mit ArrayObject nichts gewonnen ausser einem zusätzlichen Objekt im Speicher.

Interessant wird die Klasse an dem Punkt, an dem Verhalten mit den Daten mitreisen soll. Ein Warenkorb, der ungültige Positionen gar nicht erst annimmt. Eine Konfiguration, die einen fehlenden Schlüssel mit einer verständlichen Meldung quittiert statt mit einer Warning. Eine Sammlung, die beim Iterieren immer sortiert ausgibt, ohne dass der Aufrufer daran denken muss. In all diesen Fällen willst du den bequemen Klammerzugriff behalten und trotzdem eine Stelle haben, an der Regeln greifen.

Der zweite Grund ist die Übergabesemantik. Ein Array wird in PHP kopiert, sobald es geschrieben wird. Ein PHP ArrayObject wird als Objekt weitergereicht, also per Handle. Wer eine Sammlung durch mehrere Funktionen schleust und Änderungen behalten will, spart sich damit die Referenz-Kaufmanns-Und im Funktionskopf.

Ein PHP ArrayObject erzeugen und benutzen

Der Konstruktor nimmt ein vorhandenes Array entgegen. Danach verhält sich ein PHP ArrayObject bei den drei wichtigsten Zugriffsarten wie ein Array: Klammerzugriff, count() und foreach.

<?php

$korb = new ArrayObject(['Brot', 'Milch']);

$korb[] = 'Kaffee';
echo $korb[0]; /* Brot */
echo count($korb); /* 3 */

foreach ($korb as $position) {
echo $position . "\n";
}

Dass das funktioniert, liegt an vier Interfaces, die die Klasse mitbringt. ArrayAccess erlaubt den Klammerzugriff, Countable macht count() möglich, IteratorAggregate liefert den Iterator für foreach, und Serializable regelt das Speichern. Wer wissen will, wie solche Verträge in PHP funktionieren, findet das im Tutorial zu PHP Interfaces ausführlich erklärt.

Was nicht funktioniert, ist der Punkt, an dem die meisten zum ersten Mal stolpern.

Zurück zum Array mit getArrayCopy()

Die Array-Funktionen von PHP nehmen kein Objekt entgegen. array_map(), array_filter(), sort() und in_array() erwarten ein echtes Array und quittieren ein PHP ArrayObject mit einem TypeError. Der Ausweg heisst getArrayCopy().

<?php

$korb = new ArrayObject(['Brot', 'Milch']);

/* Falsch: array_map erwartet ein Array */
/* $gross = array_map('strtoupper', $korb); */

$gross = array_map('strtoupper', $korb->getArrayCopy());
print_r($gross); /* Array ( [0] => BROT [1] => MILCH ) */

Der Name der Methode ist wörtlich zu nehmen. Du bekommst eine Kopie, keine Referenz. Änderungen an dem zurückgegebenen Array wirken nicht auf das Objekt zurück. Wer das übersieht, sucht später lange nach Werten, die scheinbar verschwunden sind.

Eigene Logik einbauen: offsetSet() überschreiben

Jetzt kommt der eigentliche Grund, ein PHP ArrayObject einzusetzen. Beim Erben lassen sich die vier Zugriffsmethoden ersetzen, und offsetSet() ist dabei die wichtigste: sie läuft bei jedem schreibenden Klammerzugriff. Damit landet die Validierung an genau einer Stelle, egal von wo geschrieben wird.

<?php

class Warenkorb extends ArrayObject
{
public function offsetSet(mixed $schluessel, mixed $wert): void
{
if (!is_array($wert) || !isset($wert['menge'])) {
throw new InvalidArgumentException('Position braucht eine Menge.');
}
if ($wert['menge'] < 1) {
throw new InvalidArgumentException('Menge muss mindestens 1 sein.');
}
parent::offsetSet($schluessel, $wert);
}

public function gesamtmenge(): int
{
$summe = 0;
foreach ($this as $position) {
$summe += $position['menge'];
}
return $summe;
}
}

$korb = new Warenkorb();
$korb[] = ['artikel' => 'Kaffee', 'menge' => 2];
$korb[] = ['artikel' => 'Tee', 'menge' => 1];

echo $korb->gesamtmenge(); /* 3 */

/* Diese Zeile wirft eine Exception, bevor etwas gespeichert wird: */
/* $korb[] = ['artikel' => 'Zucker', 'menge' => 0]; */

Der Aufruf von parent::offsetSet() am Ende ist Pflicht. Ohne ihn prüft die Methode zwar brav, speichert aber nie etwas. Neben offsetSet() stehen offsetGet(), offsetExists() und offsetUnset() zur Verfügung, mit denen sich Lesezugriffe, Existenzprüfungen und Löschvorgänge genauso abfangen lassen. Wer sich mit dem Erben von Basisklassen noch schwertut, findet die Grundlagen unter Abstrakte Klassen in PHP.

Die Konstruktor-Flags STD_PROP_LIST und ARRAY_AS_PROPS

Der zweite Konstruktor-Parameter nimmt Flags entgegen. Praktisch relevant ist vor allem ARRAY_AS_PROPS, weil es die Elemente zusätzlich als Eigenschaften zugänglich macht.

<?php

$standard = new ArrayObject(['host' => 'localhost']);
echo $standard['host']; /* localhost */
/* echo $standard->host; Fehler: Property existiert nicht */

$alsProps = new ArrayObject(
['host' => 'localhost'],
ArrayObject::ARRAY_AS_PROPS
);
echo $alsProps['host']; /* localhost */
echo $alsProps->host; /* localhost, beides funktioniert */

Das zweite Flag, STD_PROP_LIST, betrifft einen Sonderfall: es sorgt dafür, dass echte Objekteigenschaften bei var_dump() und beim Iterieren getrennt von den Array-Elementen behandelt werden. In der Praxis brauchst du es selten. Ein häufiger Irrtum ist, an dieser Stelle die Iterator-Klasse angeben zu wollen. Die gehört an die dritte Position, nicht an die zweite.

Iterieren und sortieren

Sortierfunktionen gibt es als Methoden direkt am Objekt. Das ist bequemer, als jedes Mal über getArrayCopy() zu gehen, und es ändert die Reihenfolge im Objekt selbst.

<?php

$preise = new ArrayObject([
'Kaffee' => 8.90,
'Brot' => 2.40,
'Milch' => 1.15,
]);

$preise->uasort(fn(float $a, float $b): int => $a <=> $b);

foreach ($preise as $artikel => $preis) {
echo $artikel . ': ' . number_format($preis, 2, ',', '.') . " Euro\n";
}
/*
Milch: 1,15 Euro
Brot: 2,40 Euro
Kaffee: 8,90 Euro
*/

Zur Verfügung stehen asort(), ksort(), uasort(), uksort() und natsort(). Wer noch mehr Kontrolle braucht, tauscht über setIteratorClass() den Iterator aus, den getIterator() zurückliefert. Standardmässig ist das ein ArrayIterator.

Drei Stolperfallen, die jeden treffen

Diese drei Punkte kosten beim ersten Kontakt mit der Klasse regelmässig Zeit. Sie sind kein Fehler in PHP, sondern eine Folge davon, dass ein Objekt eben doch kein Array ist.

json_encode() liefert ein leeres Objekt

Ohne JsonSerializable serialisiert PHP nur öffentliche Eigenschaften, und die hat ein ArrayObject nicht. Heraus kommt {}. Entweder du übergibst getArrayCopy(), oder deine Klasse implementiert jsonSerialize().

Verschachtelte Schreibzugriffe greifen nicht

Ein Ausdruck wie $obj['liste'][] = 'x' läuft ins Leere, weil ein überladenes Element nicht per Referenz zurückgegeben wird. Der Weg führt über eine Zwischenvariable: auslesen, ändern, zurückschreiben.

Das Objekt wird nicht kopiert

Wer ein PHP ArrayObject an eine Funktion übergibt und dort ändert, ändert auch das Original. Bei einem Array wäre das nicht passiert. Eine echte Kopie entsteht mit clone, und selbst die ist flach.

Der erste Punkt lässt sich in wenigen Zeilen dauerhaft beheben.

<?php

$daten = new ArrayObject(['a' => 1, 'b' => 2]);
echo json_encode($daten); /* {} */
echo json_encode($daten->getArrayCopy()); /* {"a":1,"b":2} */

class Nutzdaten extends ArrayObject implements JsonSerializable
{
public function jsonSerialize(): array
{
return $this->getArrayCopy();
}
}

echo json_encode(new Nutzdaten(['a' => 1])); /* {"a":1} */

Damit sind die Grundlagen abgedeckt. Bleibt die Frage, ob die Klasse für dein Vorhaben überhaupt der richtige Ausgangspunkt ist.

PHP ArrayObject erben oder ArrayAccess selbst implementieren?

Beide Wege führen zu einer Klasse, die sich wie ein Array benutzen lässt. Der Unterschied liegt darin, wie viel du geschenkt bekommst und wie viel Ballast du mitschleppst.

Kriterium ArrayObject erweitern Interfaces selbst umsetzen
Aufwand am Anfang Gering, eine Methode genügt Höher, vier bis sechs Methoden
Kontrolle über die API Eingeschränkt, alle Basismethoden sind öffentlich Vollständig, nur was du freigibst
Typsicherheit der Elemente Nur über eigene Prüfung in offsetSet() Frei wählbar, auch getypte Methoden
Passt gut für Schnelle Kapselung, Konfiguration, kleine Sammlungen Fachliche Collections mit engem Vertrag

Die Faustregel: solange du dem Aufrufer ruhig alle Array-Operationen erlauben darfst, spart das Erben Arbeit. Sobald die Klasse nur ganz bestimmte Objekte aufnehmen und nur ganz bestimmte Operationen zulassen soll, ist die eigene Implementierung ehrlicher. Ein PHP ArrayObject mit fünf überschriebenen Methoden, die alle nur Exceptions werfen, ist ein Zeichen dafür, dass die Vererbung der falsche Weg war.

Der folgende Ablauf fasst die Entscheidung und den typischen Arbeitsweg zusammen.

flowchart TD
    A[Array vorhanden] --> B{Eigene Logik noetig?}
    B -->|Nein| C[Normales Array behalten]
    B -->|Ja| D[ArrayObject erweitern]
    D --> E[offsetSet ueberschreiben]
    E --> F[Zugriff bleibt wie Array]
    F --> G{Array-Funktion noetig?}
    G -->|Ja| H[getArrayCopy aufrufen]
    G -->|Nein| I[Direkt weiterarbeiten]

Ob ein Wert überhaupt ein Objekt ist, lässt sich vorher prüfen. Der Schnelltest dafür steht im Tutorial zu PHP is_object().

Fazit

PHP ArrayObject ist kein besseres Array, sondern ein Werkzeug für einen bestimmten Fall: wenn Regeln an den Daten hängen sollen und der Klammerzugriff trotzdem bleiben darf. Für reine Datenhaltung bleibt das normale Array die richtige Wahl.

Drei Dinge reichen für den Einstieg. Erzeugen mit dem Konstruktor, zurück ins Array mit getArrayCopy(), und eigene Logik durch das Überschreiben von offsetSet(). Wer dazu die drei Stolperfallen kennt, spart sich die Fehlersuche, die sonst bei json_encode() oder beim ersten array_map() beginnt.

 


 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.