Какой магический метод в PHP используется для доступа к объекту как к массиву?

Ответ

Чтобы объект в PHP мог использоваться как массив (с синтаксисом $obj['key']), он должен реализовывать интерфейс ArrayAccess. Этот интерфейс требует определения четырех методов:

  1. offsetExists($offset): bool — проверяет, существует ли элемент по ключу.
  2. offsetGet($offset): mixed — возвращает значение по ключу.
  3. offsetSet($offset, $value): void — устанавливает значение по ключу.
  4. offsetUnset($offset): void — удаляет элемент по ключу.

Практический пример — коллекция:

class ItemCollection implements ArrayAccess
{
    private array $items = [];

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

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

    public function offsetSet($offset, $value): void
    {
        if (is_null($offset)) {
            $this->items[] = $value; // Добавление в конец, как $array[]
        } else {
            $this->items[$offset] = $value;
        }
    }

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

// Использование
$cart = new ItemCollection();
$cart['apple'] = 5;      // Вызовет offsetSet
$count = $cart['apple']; // Вызовет offsetGet, вернет 5
isset($cart['pear']);    // Вызовет offsetExists, вернет false
unset($cart['apple']);   // Вызовет offsetUnset

Это мощный инструмент для создания объектов, которые ведут себя как нативные структуры данных.

Ответ 18+ 🔞

Ну ты представляешь, в PHP можно сделать так, чтобы твой объект вёл себя как самый обычный массив, с квадратными скобками и всем таким. Это же ёперный театр какой-то! Но для этого надо, чтобы твой класс реализовал интерфейс ArrayAccess. А это значит, что придётся написать четыре метода, иначе нихуя не получится.

Вот эти четыре стража порядка:

  1. offsetExists($offset): bool — проверяет, есть ли такой ключ, или мы тут воздух сотрясаем.
  2. offsetGet($offset): mixed — достаёт значение по ключу, если оно, конечно, есть.
  3. offsetSet($offset, $value): void — кладёт значение по ключу. Тут, кстати, есть хитрая жопа: если ключ не указан (как при $array[] = 'value'), то $offset будет null, и надо добавить элемент в конец.
  4. offsetUnset($offset): void — просто выкидывает элемент нахуй, как будто его и не было.

Смотри, как это выглядит на практике. Допустим, мы делаем корзину для покупок:

class ItemCollection implements ArrayAccess
{
    private array $items = [];

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

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

    public function offsetSet($offset, $value): void
    {
        if (is_null($offset)) {
            $this->items[] = $value; // Классическое "добавь в конец"
        } else {
            $this->items[$offset] = $value;
        }
    }

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

// А теперь используем, и волнение ебать какое!
$cart = new ItemCollection();
$cart['apple'] = 5;      // Тихо вызовется offsetSet
$count = $cart['apple']; // Тут сработает offsetGet, вернёт 5
isset($cart['pear']);    // offsetExists скажет false, груш нет
unset($cart['apple']);   // И offsetUnset сотрёт яблоко в порошок

Вот такая магия, чувак. Получается мощнейший инструмент, чтобы заставить объекты прикидываться нативными массивами. Сам от себя охуел, когда впервые разобрался.