Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Nuove classi built-in

Iteratori e ArrayObjects: nuovi strumenti per il programmatore PHP
Iteratori e ArrayObjects: nuovi strumenti per il programmatore PHP
Link copiato negli appunti

Oltre al potenziamento del modello ad oggetti, gli sviluppatori hanno deciso di aggiungere alla quinta versione di PHP una serie di classi built-in molto interessanti. Queste classi arricchiscono il comportamento di PHP e la potenzialità del suo modello ad oggetti aggiungendo il supporto per strutture dato molto potenti derivate dai pattern di sviluppo più comuni ed utilizzati.

Il primo che ho deciso di trattare è il pattern Iterator. Un iteratore è un oggetto che si comporta come una lista da cui è possibile recuperare ciclicamente gli elementi, con la differenza che la lista non è (normalmente) già salvata in memoria ma gli elementi successivi a quello corrente vengono generati su richiesta. Questo permette iterazioni su liste virtualmente infinite o di cui non si conoscono a priori le dimensioni. Gli iteratori possono essere utilizzati in congiunzione con il costrutto foreach come se si trattasse di normali array.

Vediamo un esempio molto semplice di iteratore in PHP:

<?php
<?php

class MiaListaIterator implements Iterator
{
    private $array;
    private $valid;
    
    public function __construct($array)
    {
        $this->array = $array;
        $this->valid = false;
    }
   
    public function rewind()
    {
        $this->valid = (FALSE !== reset($this->array));
    }

    public function current()
    {
        return current($this->array);
    }
   
    public function key()
    {
        return key($this->array);
    }

    public function valid()
    {
        return $this->valid;
    }
   
    public function next()
    {
        $this->valid = (FALSE !== next($this->array));
    }
}

class MiaLista implements IteratorAggregate
{
    private $range;

    public function __construct($max)
    {
        $this->range = range(0, $max);
    }
   
    public function getIterator()
    {
        return new  MiaListaIterator($this->range);
    }
}

$prova = new MiaLista(500);
foreach($prova as $item)
{
    echo $item.<br />;
}

?> 

Come potete notare dal codice intervengono le interfaccee Iterator ed IteratorAggregate. La prima serve per permettere a PHP di assicurarsi che l'iteratore recuperato segua una struttura precisa che permette di operare sull'elemento come se fosse un array (recuperando la chiave corrente, il prossimo elemento, l'elemento corrente, o riavvolgendo), mentre la seconda serve per assicurarsi che ogni oggetto utilizzato da foreach come un'array possa restituire un iteratore in modo corretto, tramite getIterator. 

L'esempio in realtà non è molto significativo perchè lo stesso comportamento potrebbe essere ottenuto utilizzando un normale array. Ma pensiamo al recupero di memoria che potrebbe avvenire in questo caso:

<?php

class MiaListaIterator implements Iterator
{
    private $max;
    private $valid;
    private $current;
    
    public function __construct($max)
    {
        $this->max  = $max;
        $this->current = 0;
        $this->valid = true;
    }
   
    public function rewind()
    {
        $this->current = 0;
        $this->valid = true;
    }

    public function current()
    {
        return $this->current;
    }
   
    public function key()
    {
        return $this->current;
    }

    public function valid()
    {
        return $this->valid;
    }
   
    public function next()
    {
        $this->valid = ++$this->current > $this->max;
    }
}

class MiaLista implements IteratorAggregate
{
    private $range;

    public function __construct($max)
    {
        $this->range = $max;
    }
   
    public function getIterator()
    {
        return new  MiaListaIterator($this->range);
    }
}

$prova = new MiaLista(5000000000);
foreach($prova as $item)
{
    echo $item.<br />;
}

?> 

Con questo codice iteriamo su un numero molto elevato di elementi senza consumare eccessiva memoria. Sarebbe stato molto duro ottenere lo stesso risultato utilizzando un array di cinque miliardi di elementi. La SPL implementa iteratori per molte tipologie di dato e strutture (array, directory e molto altro), quindi consiglio di studiarla per evitare di ripetere le operazioni già fatte nativamente da altri.

Un'altra classe che ritengo molto interessante è ArrayObject, che permette ad un oggetto di assumere il comportamento di un normale array, con la possibilità di accedere ai suoi elementi utilizzando le parentesi quadre.

<?php

class Users extends ArrayObject
{
    private $db;
    
    public function __construct($db)
    {
        $this->db = $db;
    }
   
    public function offsetGet($index)
    {
        $result = $this->db->query("SELECT * FROM users WHERE name = '".$index."'");
        return $result->fetch_assoc();
    }

    public function offsetSet($index, $value)
    {
        $this->db->query("UPDATE users SET surname = '".$value."' WHERE name = '".$index."'");
    }

    public function offsetExists($index)
    {
        $result = $this->db->query("SELECT * FROM users WHERE name = '".$index."'");
        return $result->num_rows > 0;
    }

    public function offsetUnset($index)
    {
        $this->db->query("DELETE FROM users WHERE name = '".$index."'");
    }
}

$utenti = new Users;
echo $utenti['Gabriele'];
$utenti['Paolo'] = 'Rossi';
unset($utenti['Federico']);

?> 

Questo esempio vi fa comprendere il funzionamento di ArrayObject: una volta implementati i metodi sopra elencati, possiamo tranquillamente operare sull'istanza dell'oggetto come se fosse un'array. Ovviamente sconsiglio di utilizzare un sistema simile per gestire gli utenti, ma ArrayObject può risultare molto utile in molte situazioni di programmazione avanzata.


Ti consigliamo anche