使用实现ArrayAccess和Iterator的对象作为可变参数

时间:2016-02-05 12:06:02

标签: php arrays variadic

我有一个实现ArrayAccessIterator的课程。

我正在试图弄清楚如何将此对象的variadic参数传递给像array_merge这样的本机函数:

array_merge(...$object);

令我失望的是,我收到一条错误消息,指出$object不是数组。

array_merge(): Argument #1 is not an array

我已经查看了其他界面,但其中没有一个看起来很明显:IteratorAggregateSerializableCountable。结果ArrayObject也是死路一条。

我确实有一个转换为数组的getter。但我只是通过实现ArrayAccess或Iterator来发现我的$ object转换为数组,因为它是关于展开数组的。

我可以实现另一个接口来使我的类更像数组吗?

1 个答案:

答案 0 :(得分:0)

这是the migration guide from 5.5.x to 5.6.x in the manual中记录的新语言功能(参数通过...解压缩),您必须在5.6.x运行前。

如果无法升级运行时,则必须使用getter将其转换为数组(类似于ArrayObject's getArrayCopy):

call_user_func_array('array_merge', $arr->getArrayCopy());

<强>测试

下面的代码(基于PHP的ArrayAccessIterator的文档示例)在PHP 5.6.25.6.177.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]);
      }
}