Uczymy się implementować jeden z ważniejszych interfejsów PHP – ArrayAccess. Do dzieła.

Tworzymy klasę dla obiektu tablicy asocjacyjnej – i tylko takiego:

class ArrAssoc implements ArrayAccess {

    public $container = array();
    public static $id = 1;

   
}

W container trzymamy tablicę, w id – identyfikator, gdyby ktoś próbował robić push na naszym obiekcie dla tworzenia kluczy.

Teraz trzy proste metody, niemal niezmienne w większości takich klas:

class ArrAssoc implements ArrayAccess {

    public $container = array();
    public static $id = 1;

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

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

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

Same nazwy i zwracane typy opisują co tu się dzieje. Do pełni szczęścia brakuje nam jeszcze jednej metody:

class ArrAssoc implements ArrayAccess {

    public $container = array();
    public static $id = 1;

    public function offsetSet($offset, $value): void {
        
        if (is_null($offset)) {
            $key = "key_" . static::$id++;
            $this->container[$key] = $value;
        } else {
            if(!is_string($offset))
                return;
            $this->container[$offset] = $value;
        }
    }

    //(...)
}

Mamy tutaj obsługę operatora pushującego []= oraz obsługę przypisywania po kluczu.

Zobaczmy, jak to wszystko działa:

$assoc = new ArrAssoc;
$assoc["name"] = 'John';
$assoc["age"] = 23;

echo $assoc["name"];
//John
echo $assoc["age"];
//23

$assoc[] = "blabla";
$assoc[] = "blablabla";
$assoc[1] = "not gonna happen";

print_r($assoc);
//ArrAssoc Object ( 
//[container] => Array ( [name] => John [age] => 23 [key_1] => blabla [key_2] => blablabla ) 
//)