简体   繁体   中英

PHP Traversable type hint

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?

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.

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);

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)
       ));
    }
}

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM