59 votes

Objets itératifs et indications de type de tableau?

J'ai beaucoup de fonctions que soit le type de conseils de tableaux ou de l'utilisation is_array() pour vérifier le tableau-ness d'une variable.

Maintenant, je commence à utiliser des objets qui sont itératif. Ils mettent en oeuvre Iterator ou IteratorAggregate. Seront-elles acceptées comme des tableaux si elles passent par type hinting, ou subir is_array()?

Si j'ai modifier mon code, est-il un générique sorte d' is_iterable(), ou dois-je faire quelque chose comme:

if ( is_array($var) OR $var instance_of Iterable OR $var instanceof IteratorAggregate ) { ... }

Quelles sont les autres itérable interfaces sont là-bas?

76voto

NullUserException Points 42268

Je pense que tu veux dire instanceof Iterator, PHP n'est pas un Iterable interface. Il a un Traversable interface bien. Iterator et IteratorAggregate à la fois d'étendre Traversable (et autant que je sache, ils sont les seuls à le faire).

Mais non, les objets de mise en œuvre de Traversable ne passera pas l' is_array() chèque, ni il y a un haut- is_iterable() fonction. Un contrôle que vous pouvez utiliser est

function is_iterable($var) {
    return (is_array($var) || $var instanceof Traversable);
}

12voto

Isaac Points 389

En fait, j'ai dû ajouter un contrôle pour stdClass, car les instances de stdClass fonctionnent dans des boucles foreach, mais stdClass n'implémente pas Traversable:

 function is_iterable($var) {
    return (is_array($var) || $var instanceof Traversable || $var instanceof stdClass);
}
 

4voto

Tivie Points 4581

J'utilise un simple (et peut-être un peu hackish) moyen de tester la "iterability".

function is_iterable($var) {
    set_error_handler(function ($errno, $errstr, $errfile, $errline, array $errcontext)
    {
        throw new \ErrorException($errstr, null, $errno, $errfile, $errline);
    });

    try {
        foreach ($var as $v) {
            break;
        }
    } catch (\ErrorException $e) {
        restore_error_handler();
        return false;
    }
    restore_error_handler();
    return true;
}

Lorsque vous essayez de boucle non itératif variable PHP lance un avertissement. Par la fixation d'un gestionnaire d'erreur personnalisé avant la tentative de réitérer, vous pouvez transformer une erreur dans une exception vous permettant ainsi d'utiliser un bloc try/catch. Ensuite vous restaurer le précédent gestionnaire d'erreur pour ne pas perturber le déroulement du programme.

Voici un petit cas de test (test en PHP 5.3.15):

class Foo {
    public $a = 'one';
    public $b = 'two';
}

$foo = new Foo();
$bar = array('d','e','f');
$baz = 'string';
$bazinga = 1;
$boo = new StdClass();    

var_dump(is_iterable($foo)); //boolean true
var_dump(is_iterable($bar)); //boolean true
var_dump(is_iterable($baz)); //boolean false
var_dump(is_iterable($bazinga)); //bolean false
var_dump(is_iterable($boo)); //bolean true

1voto

Raoul Duke Points 2091

Malheureusement, vous ne pourrez pas utiliser d'indications de type pour cela et devrez faire les choses is_array($var) or $var instanceof ArrayAccess . C’est un problème connu mais, autant que je sache, il n’est toujours pas résolu. Au moins, cela ne fonctionne pas avec PHP 5.3.2 que je viens de tester.

0voto

Jon Gilbert Points 286

Vous POUVEZ utiliser les indicateurs de type si vous passez à l’utilisation d’objets itérables.

 protected function doSomethingWithIterableObject(Iterator $iterableObject) {}
 

ou

 protected function doSomethingWithIterableObject(Traversable $iterableObject) {}
 

Cependant, cela ne peut pas être utilisé pour accepter des objets et des tableaux itérables en même temps. Si vous voulez vraiment faire cela, essayez de créer une fonction wrapper qui ressemble à ceci:

 // generic function (use name of original function) for old code
// (new code may call the appropriate function directly)
public function doSomethingIterable($iterable)
{
    if (is_array($iterable)) {
        return $this->doSomethingIterableWithArray($iterable);
    }
    if ($iterable instanceof Traversable) {
        return $this->doSomethingIterableWithObject($iterable);
    }
    return null;
}
public function doSomethingIterableWithArray(array $iterable)
{
    return $this->myIterableFunction($iterable);
}
public function doSomethingIterableWithObject(Iterator $iterable)
{
    return $this->myIterableFunction($iterable);
}
protected function myIterableFunction($iterable)
{
    // no type checking here
    $result = null;
    foreach ($iterable as $item)
    {
        // do stuff
    }
    return $result;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X