W3docs

PHP Iterables

Gli iterabili PHP includono array e oggetti Traversable che si possono scorrere con foreach. Scopri come crearli, usarli e quando scegliere i generatori.

Introduzione agli iterabili PHP

In PHP, un iterable è qualsiasi cosa su cui si può eseguire un ciclo con foreach. Comprende due tipi di valori:

  1. Array — la struttura dati comune che contiene una raccolta ordinata di coppie chiave/valore.
  2. Oggetti Traversable — oggetti che PHP sa come percorrere, perché implementano l'interfaccia built-in Traversable (in pratica tramite Iterator o IteratorAggregate, oppure come generatore).

PHP 7.1 ha introdotto lo pseudo-tipo iterable per poter dichiarare "dammi qualsiasi cosa su cui posso fare foreach" senza preoccuparsi se chi chiama passa un array o un oggetto. Questa pagina spiega cosa si considera iterable, come creare e attraversare ogni tipo, e quando usare gli iterable lazy che i generatori offrono.

Questo capitolo si basa su PHP Arrays e il ciclo foreach. Se non hai familiarità con uno dei due, leggi prima quelli.

Array: l'iterable più comune

Gli array esistono in due varianti, e l'unica differenza è il tipo di chiave utilizzato:

  • Un array indicizzato memorizza i valori sotto chiavi intere automatiche, a partire da 0. Vedi Indexed Arrays.
  • Un array associativo utilizza stringhe (o interi a scelta) come chiavi. Vedi Associative Arrays.

Un singolo array può mescolare entrambi gli stili, e i valori possono essere di qualsiasi tipo di dato.

Creare e accedere agli array

Crea un array con parentesi quadre, poi leggi un valore tramite la sua chiave:

PHP define and access an array

<?php
$fruits  = ["apple", "banana", "cherry"];           // indexed
$student = ["name" => "John Doe", "age" => 25];      // associative

echo $fruits[0] . "\n";        // apple   (first element, index 0)
echo $student["name"] . "\n";  // John Doe

Output:

apple
John Doe

Si noti che gli array indicizzati sono a base zero, quindi $fruits[0] è il primo elemento.

Iterare un array con foreach

foreach è il modo idiomatico per scorrere un iterable. Per un array indicizzato di solito si vuole solo il valore; per un array associativo si vogliono tipicamente sia la chiave che il valore:

PHP iterate over arrays

<?php
$fruits  = ["apple", "banana", "cherry"];
$student = ["name" => "John Doe", "age" => 25];

foreach ($fruits as $fruit) {
    echo $fruit . "\n";
}

foreach ($student as $key => $value) {
    echo "$key: $value\n";
}

Output:

apple
banana
cherry
name: John Doe
age: 25

Funzioni utili per gli array

PHP include decine di funzioni per array. Alcune che userai continuamente:

  • array_keys($arr) — restituisce tutte le chiavi come nuovo array.
  • array_values($arr) — restituisce tutti i valori, re-indicizzati da 0.
  • count($arr) — restituisce il numero di elementi.
  • sort($arr) — ordina i valori in modo crescente in place, restituisce true in caso di successo (non restituisce l'array ordinato).
  • in_array($needle, $arr)true se il valore esiste.

PHP array functions in action

<?php
$scores = [40, 10, 30];

echo count($scores) . "\n";              // 3
print_r(array_keys($scores));            // [0, 1, 2]

sort($scores);                            // modifies $scores in place
print_r($scores);                         // [10, 30, 40]

Output:

3
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
)
Array
(
    [0] => 10
    [1] => 30
    [2] => 40
)

Lo pseudo-tipo iterable

iterable non è una classe — è un type hint che significa "array o Traversable". Usalo su un parametro o tipo di ritorno quando la tua funzione deve solo fare un ciclo, e non vuoi costringere chi chiama a convertire i propri dati in un semplice array.

PHP iterable type hint

<?php
function sumAll(iterable $numbers): int
{
    $total = 0;
    foreach ($numbers as $n) {
        $total += $n;
    }
    return $total;
}

echo sumAll([1, 2, 3]) . "\n";          // works with an array

function countToThree(): iterable {     // a generator is also iterable
    yield 1;
    yield 2;
    yield 3;
}
echo sumAll(countToThree()) . "\n";     // works with a Traversable too

Output:

6
6

Il vantaggio: sumAll() accetta sia un array normale che uno stream generato pigro senza codice aggiuntivo. Vedi PHP Functions per ulteriori informazioni sui type hint.

Generatori: iterable lazy

Un generatore è una funzione che usa yield invece di return. Produce i valori uno alla volta, solo quando il ciclo chiede il successivo, quindi non costruisce mai l'intera raccolta in memoria. Questo è ideale per sequenze grandi o infinite.

PHP generator example

<?php
function range_lazy(int $start, int $end): iterable
{
    for ($i = $start; $i <= $end; $i++) {
        yield $i;          // pauses here and resumes on the next iteration
    }
}

foreach (range_lazy(1, 5) as $value) {
    echo $value . " ";
}
echo "\n";

Output:

1 2 3 4 5

Poiché nulla viene memorizzato, range_lazy(1, 1_000_000) usa la stessa piccola quantità di memoria di range_lazy(1, 5).

Oggetti iterabili personalizzati con Iterator

Quando vuoi il controllo completo su come viene percorso un oggetto, implementa l'interfaccia Iterator. Richiede cinque metodi che foreach chiama internamente: rewind(), valid(), current(), key() e next().

PHP custom Iterator

<?php
class EvenNumbers implements Iterator
{
    private int $position = 0;

    public function __construct(private array $items) {}

    public function rewind(): void  { $this->position = 0; }
    public function valid(): bool   { return isset($this->items[$this->position]); }
    public function current(): mixed { return $this->items[$this->position]; }
    public function key(): mixed    { return $this->position; }
    public function next(): void    { $this->position++; }
}

$evens = new EvenNumbers([2, 4, 6]);
foreach ($evens as $n) {
    echo $n . " ";
}
echo "\n";

Output:

2 4 6

Nella maggior parte dei casi un generatore è più semplice di una classe Iterator completa — ricorri a Iterator solo quando hai bisogno di un comportamento personalizzato di rewind/key o vuoi esporre l'iterazione come parte dell'API pubblica di un oggetto.

Verificare se un valore è iterable

Usa is_iterable() per verificare in fase di esecuzione se un valore può essere passato a foreach:

PHP is_iterable check

<?php
var_dump(is_iterable([1, 2, 3]));                 // bool(true)
var_dump(is_iterable("a string"));                // bool(false)
var_dump(is_iterable((function () { yield 1; })())); // bool(true)

Output:

bool(true)
bool(false)
bool(true)

Conclusione

"Iterable" in PHP significa semplicemente iterabile con foreach — e questo comprende array, oggetti Iterator/IteratorAggregate e generatori allo stesso modo. Usa i normali array per le raccolte ordinarie, il type hint iterable per scrivere funzioni che accettano qualsiasi di essi, e i generatori quando la memoria è importante o la sequenza è grande. Con questi strumenti puoi modellare i dati in modo efficiente e mantenere le tue API flessibili.

Esercitazione

Pratica
Cosa si può considerare un Iterable in PHP?
Cosa si può considerare un Iterable in PHP?
Was this page helpful?