У меня есть относительно простая функция, которая использует 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
Есть ли способ набрать подсказку или это невозможно?
PHP 7.1 представляет для этой цели объявление iterable
типа , которое принимает как массивы, так и экземпляры \Traversable
.
В предыдущих версиях вам придется опустить объявление типа.
В этом есть ошибка: # 41942 . Закрыто как «не ошибка». Поскольку массивы PHP не являются объектами, они не могут реализовать интерфейс и, таким образом, нет способа набрать hint как 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);
Та же проблема. Я отказался, я просто вручную закодировал все в функции.
Это должно дать вам необходимую функциональность:
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) )); } }
Проблема в том, что массивы не являются объектами, поэтому они не могут реализовать интерфейс. Таким образом, вы не можете вводить подсказки как для array
и для Traversable
.