Start · Sprachen · PHP · Referenz · ArrayAccess

ArrayAccess

Interface

Interface, das Objekte befähigt, mit der Array-Syntax (<code>$obj['key']</code>) gelesen und geschrieben zu werden.

seit PHP 5.0.0 Kategorie: misc

Signatur

interface ArrayAccess

Beschreibung

ArrayAccess ist ein eingebautes PHP-Interface, das vier Methoden vorschreibt. Implementiert eine Klasse dieses Interface, können ihre Instanzen mit der gewohnten Array-Schreibweise ($obj['key'], isset($obj['key']), unset($obj['key'])) verwendet werden, ohne ein echtes Array zu sein.

Das Interface eignet sich hervorragend für Datenzugriffs-Klassen, Konfigurations-Container oder Collections, die eine benutzerfreundliche, vertraute API bieten sollen. Frameworks wie Symfony oder Laravel nutzen ArrayAccess intensiv, etwa für Request-Objekte oder den Service-Container.

Die vier Pflichtmethoden sind: offsetExists() (entspricht isset()), offsetGet() (Lesezugriff), offsetSet() (Schreibzugriff) und offsetUnset() (entspricht unset()). Sie müssen in der Klasse vollständig implementiert werden, auch wenn einzelne Operationen nicht unterstützt werden sollen (dann ggf. eine Exception werfen).

ArrayAccess lässt sich gut mit Countable und Iterator kombinieren, um ein Objekt zu schaffen, das sich nahezu vollständig wie ein Array verhält, aber die Vorteile objektorientierter Typsicherheit und Kapselung bietet.

Beispiele

Einfacher Konfigurations-Container mit ArrayAccess

<?php

class Config implements ArrayAccess
{
    private array $data = [];

    public function offsetExists(mixed $offset): bool
    {
        return isset($this->data[$offset]);
    }

    public function offsetGet(mixed $offset): mixed
    {
        return $this->data[$offset] ?? null;
    }

    public function offsetSet(mixed $offset, mixed $value): void
    {
        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function offsetUnset(mixed $offset): void
    {
        unset($this->data[$offset]);
    }
}

$config = new Config();
$config['db_host'] = 'localhost';
$config['db_port'] = 3306;

echo $config['db_host'] . PHP_EOL; // localhost
echo isset($config['db_port']) ? 'Port gesetzt' : 'kein Port';
unset($config['db_port']);
echo PHP_EOL . (isset($config['db_port']) ? 'Port gesetzt' : 'Port nicht mehr gesetzt');
localhost Port gesetzt Port nicht mehr gesetzt

Read-only-Objekt: Schreibzugriff per Exception verbieten

<?php

class ReadOnlyMap implements ArrayAccess
{
    public function __construct(private array $data) {}

    public function offsetExists(mixed $offset): bool
    {
        return array_key_exists($offset, $this->data);
    }

    public function offsetGet(mixed $offset): mixed
    {
        if (!$this->offsetExists($offset)) {
            throw new OutOfBoundsException("Schlüssel '$offset' nicht gefunden.");
        }
        return $this->data[$offset];
    }

    public function offsetSet(mixed $offset, mixed $value): void
    {
        throw new LogicException('Diese Map ist schreibgeschützt.');
    }

    public function offsetUnset(mixed $offset): void
    {
        throw new LogicException('Diese Map ist schreibgeschützt.');
    }
}

$map = new ReadOnlyMap(['sprache' => 'PHP', 'version' => '8.3']);
echo $map['sprache'] . ' ' . $map['version'] . PHP_EOL;

try {
    $map['neu'] = 'Wert';
} catch (LogicException $e) {
    echo 'Fehler: ' . $e->getMessage();
}
PHP 8.3 Fehler: Diese Map ist schreibgeschützt.

// Wichtig · Fallstricke

Kein echtes Array: Objekte, die ArrayAccess implementieren, sind keine Arrays. Funktionen wie array_map(), array_keys() etc. funktionieren nicht direkt darauf. Um Iterierbarkeit zu erhalten, sollte zusätzlich Iterator oder IteratorAggregate implementiert werden.

Typangaben ab PHP 8.1: Ab PHP 8.1 sollten die Parameter von offsetGet, offsetSet usw. mit mixed typisiert werden. Abweichende Typen können zu Kompatibilitätswarnungen führen.

offsetGet per Referenz: Wenn offsetGet() per Referenz (&) zurückgeben soll (etwa für $obj['key'][] = 'wert'), muss die Methode explizit & in der Signatur tragen. Dies ist ein häufiger Fallstrick bei verschachtelten Schreibzugriffen.