piątek, 4 października 2019

ArrayAccess Interface

Jest to interfejs dzięki któremu możemy sprawić że nasz obiekt będzie realizował interfejs dostępu jak w typowej PHP'owej tablicy.

Posiada cztery sygnatury metod które musimy uzbroić w implementacje:

  • offsetExists(mixed $offset) : bool
    • Tutaj sprawdzamy czy klucz array'ki do którego próbujemy się odwołać w ogóle istnieje,
  • offsetGet(mixed $offset) : mixed
    • Zwracamy pożądany klucz array'a. Na wypadek gdy takowy nie istnieje warto zwrócić null,
  • offsetSet(mixed $offset ,mixed $value) : void
    • Służy do dodawania nowego klucza do array'a. Pierwszy parametr definiuje klucz array'a do którego wstawimy wartość którą reprezentuje drugi parametr,
  • offsetUnset(mixed $offset) : void
    • Tutaj musimy zaimplementować działanie kasowania wartości array'a.
Warto nadmienić, że implementując ten interfejs do naszej klasy, jej instancji nie będziemy mogli
  • trawersować w pętli foreach() - do tego jest np. interfejs Iterator,
    • przekazanie takiego obiektu w następujący sposób:  foreach($arrayAccessObject as $value) {...} sprawi, że pętla nie wykona się ani razu,
  • 'policzyć ilości' elementów array'a w funkcji count() czy sizeof() - aby to osiągnąć klasa musi implementować interfejs Countable
    • wywołanie funkcji count($arrayAccessObject) gdzie przekazana instancja będzie umożliwiała dostęp np. do trzech kluczy tablicy:  $arrayAccessObject['name']; $arrayAccessObject['age']; $arrayAccessObject['email'] i tak zwróci wartość (int) 1.
  • sprawdzać czy klucz istnieje za pomocą funkcji array_key_exists(). Ponieważ implementowana funkcja offsetExists() i tak nie zostanie automatycznie uruchomiona. To samo tyczy się w zasadzie każdej funkcji array'owej jak np. array_diff() czy array_push() - to po prostu nie zadziała.
co nie jest żadnym problemem gdy dysponujemy zwykłą tablicą.

Przykładowa implementacja:

class Person implements ArrayAccess {
    
    /**
     * @var string 
     */
    private $name;

    /**
     * @var int
     */
    private $age;

    /**
     * @var string 
     */
    private $email;

    public function __construct(
        string $name
        int    $age
        string $email
    ) {
        $this->name  = $name;
$this->age   = $age;
$this->email = $email;
    }
    /**
     * @inheritdoc
     */
    public function offsetSet($propertyName, $propertyValue) {
        $this->{$propertyName} = $propertyValue;
    }
    /**
     * @inheritdoc
     */
    public function offsetExists($propertyName) {
        return property_exists($this, $propertyName);
    }
    /**
     * @inheritdoc
     */
    public function offsetUnset($propertyName) {
        unset($this->{$propertyName});
    }

    /**
     * @inheritdoc
     */
    public function offsetGet($propertyName) {
        return property_exists($this, $propertyName
               ? $this->{$propertyName} : null;
    }
}

$person = new Person('John', 30, 'john@gmail.com');
$person['lastName'] = 'Smith';
echo $person['lastName']; // Smith


Ciekawostki: 
  • Interfejs jest wykorzystywany w klasie SplObjectStorage.
  • jeżeli zapewnimy odpowiednią obsługę to jako kluczy (w klasie klienta) będziemy mogli użyć np. obiektów, a nie tylko string'ów i integer'ów.
  • jeśli koniecznie chcemy korzystać z funkcji array'owych to możemy zwracać całą array'kę z klasy implementującej ArrayAccess Interface poprzez jakąś metodę bądź - trochę wygodniejsze rozwiązanie z perspektywy klas klienckich - za pomocą metody magicznej __invoke(), wyglądało by to wtedy mniej więcej tak:
    • array_push($arrayAccessObject(), 'newValue');







Brak komentarzy:

Prześlij komentarz