Подсказка о проходимом типе PHP


У меня есть относительно простая функция, которая использует foreach

function foo($t) {
     $result;
     foreach($t as $val) {
         $result = dosomething($result, $val);
     }
     return $result;
}

Я хотел бы ввести подсказку, и Traversable кажется, это точная подсказка типа, которая мне нужна

 function foo(Traversable $t) {

Однако это дает E_RECOVERABLE_ERROR при использовании массива (который, конечно, можно использовать в foreach): пример

 Argument 1 passed to foo() must implement interface Traversable, array given

Есть ли способ ввести подсказку или это невозможно?

Author: dave, 2013-06-10

4 answers

PHP 7.1 представляет iterable объявление типа для этой цели, которое принимает как массивы, так и экземпляры \Traversable.

В предыдущих версиях вам придется опустить объявление типа.

 10
Author: Andrea, 2017-07-09 12:02:52

В этом есть ошибка: #41942. Закрыт как "не ошибка". Поскольку массивы PHP не являются объектами, они не могут реализовать интерфейс, и поэтому нет способа ввести подсказку как array, так и Traversable.

Вы можете использовать iterator_to_array, ArrayIterator или опустите подсказку типа. Обратите внимание, что iterator_to_array скопирует весь итератор в массив и, таким образом, может быть неэффективным.

// These functions are functionally equivalent but do not all accept the same arguments
function foo(array $a) { foobar($a); }
function bar(Traversable $a) { foobar($a); }
function foobar($a) {
    foreach($a as $key => $value) {
    }
}

$array = array(1,2,3)
$traversable = new MyTraversableObject();

foo($array);
foo(iterator_to_array($traversable));

bar(new ArrayIterator($array));
bar($traversable);

foobar($array);
foobar($traversable);
 8
Author: dtech, 2014-10-06 12:42:52

Та же проблема. Я сдался, я просто вручную кодирую все в функции.

Это должно дать вам необходимую функциональность:

function MyFunction($traversable)
{
    if(!$traversable instanceof Traversable && !is_array($traversable))
    {
        throw new InvalidArgumentException(sprintf(
            'Myfunction($traversable = %s): Invalid argument $traversable.'
            ,var_export($traversable, true)
       ));
    }
}

РЕДАКТИРОВАТЬ

, Если вы хотите отобразить только тип $traversable. И если вы хотите, чтобы функциональность наследовалась в дочерних классах.

public function MyMethod($traversable)
{
    if(!$traversable instanceof Traversable && !is_array($traversable))
    {
        throw new InvalidArgumentException(sprintf(
            '%s::MyMethod($traversable): Invalid argument $traversable of type `%s`.'
            ,get_class($this)
            ,gettype($traversable)
       ));
    }
}
 3
Author: mAsT3RpEE, 2013-11-19 06:17:32

Проблема в том, что массивы не являются объектами, поэтому они не могут реализовать интерфейс. Таким образом, вы не можете ввести подсказку как array, так и Traversable.

 2
Author: bpoiss, 2013-06-10 20:38:12