У меня есть класс, который реализует оба ArrayAccess а также Итератор.
Я пытаюсь выяснить, как передать этот параметр объекта variadic в нативную функцию, как array_merge
:
array_merge(...$object);
К моему разочарованию, я получаю сообщение о том, что $object
это не массив.
array_merge(): Argument #1 is not an array
Я смотрел на эти другие интерфейсы, но ни один из них не кажется очевидным: IteratorAggregate, Сериализуемый, Счетный. Также ArrayObject оказался тупиком.
У меня есть геттер для преобразования в массив. Но я как бы прыгал, чтобы обнаружить, что мое $ object превращается в массив, просто реализуя ArrayAccess или Iterator, поскольку речь идет о развертывании массива.
Есть ли другой интерфейс, который я могу реализовать, чтобы сделать мой класс более похожим на массив?
Это новая языковая функция, как описано в руководство по миграции с 5.5.x до 5.6.x в руководстве (раздел Аргумент распаковывается через ...
), вы должны быть на5.6.x
во время выполнения.
Если вы не можете обновить вашу среду выполнения, вы должны использовать ваш геттер для преобразования его в массив (аналогично ArrayObject
«s getArrayCopy
):
call_user_func_array('array_merge', $arr->getArrayCopy());
тесты
Код ниже (на основе примеров документации PHP для ArrayAccess
а также Iterator
) успешно выполнен на PHP 5.6.2
, 5.6.17
а также 7.0.1
, Это действительно не удается на старых версиях (5.5.31
и старше).
$arr = new MyArray();
$arr[0] = array(1, 2);
$arr[1] = array(3, 4);
// MyArray
print(get_class($arr));
// Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
print_r(array_merge(...$arr));
Реализация MyArray
:
class MyArray implements ArrayAccess, Iterator
{
private $container = array();
private $position = 0;
public function getArrayCopy() {
return $this->container;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
function rewind() {
$this->position = 0;
}
function current() {
return $this->container[$this->position];
}
function key() {
return $this->position;
}
function next() {
++$this->position;
}
function valid() {
return isset($this->container[$this->position]);
}
}
Других решений пока нет …