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