Czy w PHP jest możliwy dostęp w klasie do prywatnego pola będącego tablicą, za pomocą tzw. „metod magicznych” __get i __set? Pytam, ponieważ używam wymienionych metod do uzyskiwania dostępu do pól klasy, które są typami prostymi lub obiektami i to działa całkiem przyzwoicie (wiem, że są pewne spadki wydajności ale to w chwili obecnej nie jest dla mnie kluczowe). Chciałbym niektóre utworzone przez siebie klasy wyposażyć we właściwości tablicowe. Przez pojęcie właściwości rozumiem tu mechanizm znany z języków takich jak C# czy ObjectPascal, gdzie w klasie istnieje pole, do którego dostęp odbywa się poprzez prywatne metody dostępowe (akcesory). Pozwala to np.: sprawdzać poprawność przekazywanych wartości (dla metody „set”) czy zwracać określoną wartość dla właściwości, która może nie posiadać odpowiadającego jej prywatnego pola w klasie a zwracana wartość jest np. obliczana (dla metody „get”). Żeby dobrze wyłuszczyć nurtujący mnie problem, przytoczę fragment hipotetycznej klasy:
<?php class TMyComponent { private $_count; private $_name; private $_values; public function __construct() { $this->_name = ""; } public function __get($name) { if (method_exists($this, $method)) { return $this->$method(); } } public function __set($name, $value) { if (method_exists($this, $method)) { $this->$method($value); } } private function getCount() { return $this->_count; } private function getName() { return $this->_name; } private function setName($value) { $this->_name = value; } public function getValues($index) { $item = NULL; if ($this->isIndexValid($index)) { $item = $this->_items[$index]; } return $item; } public function setValues($index, $value) { if ($this->isIndexValid($index)) { $this->replace($index, $value); } protected function isIndexValid($index) { } } ?>
Dostęp do dwóch pierwszych pól w utworzonym obiekcie wyżej podanej klasy jest dość wygodny, np.:
$myObj = new TMyComponent(); ... $n = $myObj->count; $myObj->name = "abcdef";
Niestety do pola $_values można dostać się tylko przy jawnym wywołaniu metod getValues i setValues, np.:
$oldValue = $myObj->getValues(2); // odczyt z komórki prywatnego pola klasy, gdzie pole jest tablicą $myObj->setValues(2, 64); // zapis do komórki prywatnego pola klasy, gdzie pole jest tablicą
Czy w PHP jest możliwe takie przebudowanie wyżej podanego ciągu instrukcji metod __get i __set aby można było dostać się do pola $_values w taki sposób:
$oldValue = $myObj->values[2]; // odczyt z komórki prywatnego pola klasy, gdzie $values jest właściwością tablicową (a nie polem klasy!) $myObj->values[2] = 64; // zapis do komórki prywatnego pola klasy, gdzie $values jest właściwością tablicową (a nie polem klasy!)
Wg mojej wiedzy dotyczącej PHP (z pewnością niekompletnej), tego nie da się zaimplementować. A to dlatego, ponieważ metoda magiczna __get pobiera tylko jeden argument, którym jest nazwa właściwości. Niestety nie da się przekazać indeksu komórki do tablicy. Podobnie ma się rzecz z metodą magiczną __set, która pobiera tylko dwa argumenty, którymi są nazwa właściwości i wartość podlegająca przypisaniu do prywatnego pola. Być może się mylę i da się ten problem rozwiązać (co byłoby miłym zaskoczeniem). Rzecz jednak w tym, że dość skrupulatnie przekopywałem dział Help serwisu php.net. Próbowałem także przeszukiwać różne fora i blogi dotyczące programowania w PHP. Niestety nie natknąłem się na rozwiązanie takiego problemu. Jedyne na co trafiłem to na propozycje rozszerzenia języka PHP o metody dostępowe get i set działające podobnie jak w C# (tu: https://bugs.php.net/bug.php?id=49526, ale ta propozycja została odrzucona a szkoda, bo ten mechanizm wydaje się być o wiele lepszy niż tzw. "metody magiczne").
Czy jest zatem możliwe obsłużenie w klasie prywatnego pola-tablicy za pomocą metod magicznych __get i __set?