is_iterable()
La funzione is_iterable() di PHP 7.1+ verifica se una variabile è iterabile, ovvero un array o un oggetto che implementa l'interfaccia Traversable.
Introduzione
is_iterable() è una funzione PHP integrata (disponibile da PHP 7.1) che indica se un valore può essere iterato con un ciclo foreach. Restituisce true esattamente per due tipi di valori:
- Array — ogni array è iterabile.
- Oggetti che implementano l'interfaccia
Traversable— in pratica, oggetti che implementanoIteratoroIteratorAggregate, nonché i generator (funzioni che usanoyield).
Tutto il resto — stringhe, interi, booleani, null e oggetti semplici (come stdClass) — non è iterabile, anche se intuitivamente può sembrare "simile a una lista". Questa pagina tratta la sintassi, cosa si considera iterabile, le insidie più comuni e quando l'utilizzo di is_iterable() è davvero conveniente.
Sintassi
is_iterable(mixed $value): boolAccetta un singolo argomento, $value, e restituisce un booleano:
| Argomento | Risultato |
|---|---|
| Un array | true |
Un oggetto Traversable (Iterator, IteratorAggregate, generator) | true |
Qualsiasi altra cosa (stringa, int, oggetto semplice, null, …) | false |
Da PHP 8.0 esiste anche uno pseudo-tipo corrispondente, iterable, utilizzabile come dichiarazione di tipo — vedi Quando usarla più avanti.
Esempio di base
$var1 è un array, quindi è iterabile. $var2 è una stringa — anche se è possibile accedere ai singoli caratteri tramite indice, non può essere percorsa con foreach, quindi is_iterable() restituisce false.
Cosa si considera iterabile
I casi interessanti riguardano gli oggetti. Un oggetto è iterabile solo se implementa Traversable (direttamente o tramite Iterator/IteratorAggregate), oppure se è un generator. Un oggetto semplice non lo è.
<?php
function genFn() {
yield 1;
yield 2;
}
class MyCollection implements IteratorAggregate {
private array $items = [1, 2, 3];
public function getIterator(): Iterator {
return new ArrayIterator($this->items);
}
}
var_dump(is_iterable([1, 2, 3])); // bool(true) array
var_dump(is_iterable(genFn())); // bool(true) generator
var_dump(is_iterable(new MyCollection())); // bool(true) Traversable
var_dump(is_iterable("hello")); // bool(false) string
var_dump(is_iterable(42)); // bool(false) int
var_dump(is_iterable(new stdClass())); // bool(false) plain object
var_dump(is_iterable(null)); // bool(false) null
?>Il punto chiave: un stdClass (o qualsiasi oggetto senza Traversable) restituisce false, anche se foreach può iterare sulle sue proprietà pubbliche. is_iterable() segnala deliberatamente solo i valori iterabili per contratto, non per caso.
Insidie comuni
- Le stringhe non sono iterabili. Una stringa è uno scalare, non una collezione, quindi
is_iterable("abc")èfalse. Per verificare una stringa, usa inveceis_string(). - Gli oggetti semplici falliscono.
is_iterable(new stdClass())èfalse. Se vuoi solo sapere se un valore è qualsiasi oggetto, usais_object(); se hai specificamente bisogno di un oggetto iterabile,is_iterable()è la scelta giusta. - Non è equivalente a
is_array().is_array()ètruesolo per gli array e rifiuta generator e oggettiTraversable. Usais_iterable()quando vuoi accettare sia array che oggetti iteratori. nullrestituiscefalse. Passare un valore non inizializzato onullè sicuro — restituisce semplicementefalseanziché generare un errore.
Quando usarla
Usa is_iterable() come clausola di guardia prima di un foreach, in modo che una funzione possa accettare sia un array che un iteratore lazy senza crashare su input errati:
<?php
function sumAll(mixed $data): int {
if (!is_iterable($data)) {
throw new InvalidArgumentException('Expected an iterable.');
}
$total = 0;
foreach ($data as $value) {
$total += $value;
}
return $total;
}
echo sumAll([1, 2, 3, 4]), "\n"; // 10
function counter() {
yield 5;
yield 10;
}
echo sumAll(counter()), "\n"; // 15
?>La stessa funzione gestisce sia un array semplice che un generator, poiché entrambi soddisfano is_iterable().
Spesso la scelta più pulita è la dichiarazione di tipo iterable (PHP 7.1+), che permette a PHP di imporre il vincolo automaticamente, eliminando la necessità del controllo manuale:
<?php
function sumAll(iterable $data): int {
$total = 0;
foreach ($data as $value) {
$total += $value;
}
return $total;
}
?>Ricorri alla funzione is_iterable() quando il valore è mixed e vuoi fare un branch a runtime; ricorri al type hint iterable quando l'iterabilità è un requisito obbligatorio del parametro.
Conclusione
is_iterable() risponde a una domanda precisa: questo valore può essere percorso da un ciclo foreach? Restituisce true per array e oggetti Traversable (inclusi i generator) e false per tutto il resto. Usala come guardia a runtime per input mixed, preferisci il type hint iterable quando l'iterabilità è obbligatoria, e ricorda che è più restrittiva di quanto sembri — le stringhe e gli oggetti semplici non sono iterabili. Per controlli correlati, vedi is_array(), is_object() e gettype().