Сначала цитата из руководства ole' по ArrayAccess::offsetSet()
:
Эта функция не вызывается в присваиваниях по ссылке и других косвенных изменениях размерности массива, перегруженного ArrayAccess (косвенных в том смысле, что они делаются не путем изменения размерности непосредственно, а путем изменения подразмерности или подсвойства или присвоения размерности массива по ссылке на другую переменную). Вместо этого вызывается ArrayAccess::offsetGet(). Операция будет успешной, только если этот метод вернет значение по ссылке, что возможно только начиная с версии PHP 5.3.4.
Меня это немного смущает. Похоже, это говорит о том, что (начиная с версии 5.3.4) можно определить offsetGet()
для возврата по ссылке в реализующем классе, таким образом обрабатывая присваивания по ссылке.
Итак, теперь тестовый фрагмент:
(Не обращайте внимания на отсутствие валидации и isset()
проверки)
class Test implements ArrayAccess
{
protected $data = array();
public function &offsetGet($key)
{
return $this->data[$key];
}
public function offsetSet($key, $value)
{
$this->data[$key] = $value;
}
public function offsetExists($key) { /* ... */ }
public function offsetUnset($key) { /* ... */ }
}
$test = new Test();
$test['foo'] = 'bar';
$test['foo'] = &$bar; // Fatal error: Cannot assign by reference to
// overloaded object in
var_dump($test, $bar);
Хорошо, это не работает. Тогда к чему относится эта заметка в руководстве?
Причина
Я хотел бы разрешить присваивание по ссылке через оператор массива объекту, реализующемуArrayAccess
, как показано в примере. Я исследовал это раньше и не думал, что это возможно, но вернувшись к этому из-за неопределенности, я (повторно) обнаружил это упоминание в руководстве. Теперь я просто в замешательстве.
Update: Когда я нажал Post Your Question, я понял, что это, скорее всего, относится к присвоению по ссылке на другую переменную, например $bar = &$test['foo'];
. Если это так, то прошу прощения; хотя знать, как, если это вообще возможно, присвоить по ссылке на перегруженный объект, было бы здорово.
Further elaboration: Все сводится к тому, что я хотел бы иметь следующие псевдонимы методов:
isset($obj[$key]); // $obj->has_data($key);
$value = $obj[$key]; // $obj->get_data($key);
$obj[$key] = $value; // $obj->set_data($key, $value);
$obj[$key] = &$variable; // $obj->bind_data($key, $variable);
// also, flipping the operands is a syntactic alternative
$variable = &$obj[$key]; // $obj->bind_data($key, $variable);
unset($obj[$key]); // $obj->remove_data($key);
Что касается has
, get
, set
и remove
, то они без проблем работают с поддерживаемыми методами ArrayAccess
. Функциональность связывания - вот где я в растерянности и начинаю приходить к выводу, что ограничения ArrayAccess и PHP просто запрещают это.