问题
I have a relatively simple function which uses a foreach
function foo($t) {
$result;
foreach($t as $val) {
$result = dosomething($result, $val);
}
return $result;
}
I would like to type hint, and Traversable seems to be the exact type hint I need
function foo(Traversable $t) {
However this gives a E_RECOVERABLE_ERROR
when using an array (which is of course usable in a foreach
): example
Argument 1 passed to foo() must implement interface Traversable, array given
Is there a way to type hint or is this not possible?
回答1:
PHP 7.1 introduces the iterable type declaration for this purpose, which accepts both arrays and instances of \Traversable
.
In previous versions, you'll have to omit the type declaration.
回答2:
There is a bug about this: #41942. Closed as 'not a bug'. As PHP arrays are not objects they cannot implement an interface and a such there is no way to type hint both array
and Traversable
.
You can use iterator_to_array, ArrayIterator or omit the type hint. Note that iterator_to_array will copy the whole iterator into an array an might thus be inefficient.
// 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);
回答3:
Same problem. I've given up I simply manually code everything in the function.
This should give you the functionality you want:
function MyFunction($traversable)
{
if(!$traversable instanceof Traversable && !is_array($traversable))
{
throw new InvalidArgumentException(sprintf(
'Myfunction($traversable = %s): Invalid argument $traversable.'
,var_export($traversable, true)
));
}
}
EDIT
If you only want to display type of $traversable
. And if you want the functionality inheritable in child classes.
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)
));
}
}
回答4:
The problem is, that arrays are no objects, so they can't implement an interface. So you can't type hint both, array
and Traversable
.
来源:https://stackoverflow.com/questions/17031720/php-traversable-type-hint