lunedì 30 aprile 2012

Introduzione al PHP: Gli Array - Inizializzare (Parte 1/2)

Gli array PHP sono strutture che associano ad
una chiave un valore
Gli array di PHP non sono array nel senso classico del termine. In PHP gli array sono strutture dati che creano un'associazione tra una chiave (di tipo int o stringa) e un valore, che può appartenere ad uno degli otto dati primitivi ivi compreso un array, dando luogo ad array multidimensionali. Non c'è obbligo che i dati contenuti in un array siano omogenei (dello stesso tipo), così come non c'è obbligo che le chiavi siano tutte dello stesso tipo ma possono alternarsi chiavi numeriche a chiavi stringa e dati di tipo diverso nello stesso array.

Inizializzare con il costrutto array()
Gli array possono essere definiti per mezzo del costrutto del linguaggio array(). Ad esempio

$mioArray = array();

definisce una variabile di nome $mioArray di tipo array e privo di elementi. Ne consegue che la funzione isset($mioAray) restituisce true ($mioArray esiste ed è diversa da null) ed anche empty($mioArray) restituisce true ($mioArray è un array vuoto).

E' possibile specificare gli elementi, che costituiscono l'insieme dei valori dell'array, inserendoli fra le parentesi tonde separati da una virgola:

$mioArray = array(1, 2, "Hello", 3, 4, "World", array("Nome", "Cognome"), new stdClass());

Non c'è obbligo che i dati siano omogenei nell'array, ma possono variare nel tipo. In questo caso abbiamo definito $mioArray come un vettore contenente 8 valori in cui i primi due sono int, il terzo è una stringa, il quarto e quinto sono ancora int, il sesto è una stringa, il settimo è un array e l'ottavo un puntatore ad un oggetto istanza della classe stdClass.

Abbiamo però detto che gli array in PHP creano delle associazioni tra chiavi e valori, ma le chiavi dove sono? PHP associa una chiave numerica di tipo intero, se non specificata, di valore immediatamente successivo alla più grande chiave numerica già utilizzata nell'array ovvero 0 se non è stata utilizzata ancora nessuna chiave numerica.

Ciò significa che il valore 1 ha come chiave associata 0 (lo indichiamo come 0=>1). Al valore 2, essendo la più grande chiave intera utilizzata uguale a 0, associa la chiave 1 ossia 1=>2. Per lo stesso motivo avremo 2=>"Hello", 3=>3, 4=>4, 5=>"World", 6=>array("Nome","Cognome"), 7=>new stdClass().

Volendo esplicitare le chiavi da associare ai valori si può anteporre al valore la sequenza => preceduta dalla chiave:

$mioArray = array(0=>1, 1=>2, 2=>"Hello", 3=>3, 4=>4, 5=>"World", 6=>array("Nome", "Cognome"), 7=>new stdClass());

Per quanto detto, il valore di tipo array associato alla chiave 6, ha delle chiavi implicite che sono 0=>"Nome" e 1=>"Cognome".

Graficamente lo potremmo rappresentare come:

L'array $mioArray. La chiave 6 è associata ad un valore di tipo array, quindi attraverso
un'ulteriore chiave è possibile accedere ad uno dei due valori stringa

Le chiavi possono anche essere di tipo string e non devono essere tutte dello stesso tipo all'interno dello stesso array:

$unArray = array(5=>55, 2=>63, "Nome"=>"Ciro", "Cognome"=>"Pellegrino", 0=>"Pippo", 88);
Gli array sono ordinati secondo l'inserimento non sulla chiave o sul valore
Cosa è stato fatto? Sono stati definiti due valori con chiave numerica 5 e 2, quindi due valori con chiave stringa, un valore stringa con chiave numerica, quindi un valore senza chiave, che per la regola precedente ha chiave numerica con valore successivo al massimo valore già utilizzato, ossia 6.

Tale tipo di assegnazione delle chiavi è talvolta utilizzata per far partire un array da un particolare indice. Ad esempio, se vogliamo che un array non inizi con indice 0 ma con indice 1, potremo scrivere:

$numeri = Array(1=>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);

è un vettore in cui il primo elemento ha indice 1 ed i successivi a seguire 2, 3 ...

Da PHP 5.4 è possibile sostituire il costrutto del linguaggio array() con []. E' quindi possibile definire il primo array come:

$mioArray = [1, 2, "Hello", 3, 4, "World", ["Nome", "Cognome"], new stdClass()];

Inizializzare con la sintassi delle parentesi quadre
E' anche possibile inizializzare un array assegnando i singoli elementi che lo costituiscono:


//Faccio in modo che $numeri sia un array vuoto
$numeri = array();
//Aggiungo i valori 
$numeri[] = 1;  //Chiave vale (int)0
$numeri[] = 2;  //Chiave vale (int)1
$numeri[] = 4;  //Chiave vale (int)2
$numeri[] = 8;  //...
$numeri[] = 16;
$numeri[] = 32;
...

L'istruzione $numeri = array(); fa in modo che $numeri sia definita e di tipo array. L'istruzione $mioArray[] = 2; fa in modo che PHP generi automaticamente una chiave con la regola già esposta per cui si avrà l'associazione 0=>1. L'istruzione successiva crea la coppia 1=>2, quindi 2=>4, 3=>8 e così via. L'utilizzo delle sintassi con parentesi quadra vuota permette di accodare, in un array esistente, dei valori lasciando che PHP generi le chiavi numeriche automaticamente con la regola già vista.

E' anche possibile specificare l'indice  affinché la numerazione parta da un punto di nostra scelta:

//Faccio in modo che $numeri sia un array vuoto
$numeri = array();
//Aggiungo i valori 
$numeri[1] = 2;  //Chiave 1
$numeri[] = 4;  //Chiave 2
$numeri[] = 8;  //Chiave 3
$numeri[] = 16; //...
$numeri[] = 32;
$numeri[] = 64;
...

In questo caso il primo elemento dell'array ha chiave 1 ed i successivi a seguire 2, 3, 4, ecc.

Se avessimo omesso l'istruzione $numeri = array(); si può cadere nelle seguenti circostanze:
  • $numery esiste
    • è di tipo diverso da array 
      • PHP genera un errore in esecuzione
    • è di tipo array
      • se è definito $numeri[1] questo viene aggiornato con il nuovo valore
      • se non è definito $numeri[1] viene creata l'associazione 1=>2
      • i valori successivi sono accodati all'interno di un array esistente con chiave numerica che parte dalla massima chiave numerica già utilizzata nell'array. Il risultato non è quello desiderato e gli effetti imprevedibili.
  • $numeri non esiste
    • Viene definito come array ed otteniamo il risultato atteso
Questo sistema è utilizzabile ogni qual volta si desideri estendere il contenuto di un array. Infatti, a differenza di altri linguaggi, la dimensione di un array non è stabilita a priori ma può aumentare e diminuire arbitrariamente tramite codice.

Per esempio, un modo per creare un array contenente i valori 2^i con 0<i<11:

//Definisco un array con un solo valore
$numeri = array(1=>2);
//Estendo dinamicamente l'array con nuove coppie chiave=>valore
//in cui la chiave è generata automaticamente da PHP ed il valore
//è calcolato sul valore dell'ultimo elemento inserito
for( $i=2; $i<=10; $i++)
    $numeri[] = $numeri[$i-1]*2;

equivalente a:

$numeri = array(1=>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);


Inizializzare tramite copia
Dato un array è possibile inizializzare un secondo semplicemente assegnando al secondo il primo:


$numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
$mioArray = $numeri;


Ciò perché a differenze dei linguaggi tradizionali, PHP effettua per impostazione predefinita una copia degli array, quindi andando a modificare $mioArray, $numeri resta invariato. 


Inizializzare come riferimento ad altro array
Utilizzando l'operatore riferimento (&), è possibile inizializzare una variabile come riferimento ad un dato di tipo array già esistente.

$numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
$mioArray = &$numeri;


Con tale operatore, $mioArray e $numeri fanno riferimento allo stesso dato di tipo array, quindi ogni modifica apportata a $mioArray è come se fosse apportata a $numeri e viceversa perchè afferiscono allo stesso dato.


Segue il codice dell'index.php per un progettino DemoInitArray:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Inizializzare gli array</title>
    </head>
    <body>      
        <?php
            echo '<h2>Il costrutto array()</h2>';
            echo '<h3>Definire un array vuoto</h3>';
            echo '$mioArray = array();<br />isset($mioArray);<br />empty($mioArray)';
            $mioArray = array();
            var_dump($mioArray,isset($mioArray),empty($mioArray));          
         
            echo '<h3>Popolare l\'array con dei valori</h2>';
            echo '$mioArray = array(1, 2, "Hello", 3, 4, "World", array("Nome", "Cognome"), new stdClass());';
            $mioArray = array(1, 2, "Hello", 3, 4, "World", array("Nome", "Cognome"), new stdClass());
            var_dump($mioArray);          
         
            echo '<h3>Definire un array con dati e chiavi di tipi diversi</h3>';
            echo '$unArray = array(5=>55, 2=>63, "Nome"=>"Ciro", "Cognome"=>"Pellegrino", 0=>"Pippo", 88);';
            $unArray = array(5=>55, 2=>63, "Nome"=>"Ciro", "Cognome"=>"Pellegrino", 0=>"Pippo", 88);
            var_dump($unArray);        
         
            echo '<h3>Creare un array con indici numerici che iniziano da un valore predefinito</h3>';
            echo '$numeri = Array(1=>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);';
            $numeri = Array(1=>2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
            var_dump($numeri);
            echo '<hr />';
         
            echo '<h2>La sintassi delle parentesi quadre</h2>';
            echo '<h3>Inizializzazione di un array</h3>';
            echo <<<'EOT'
//Faccio in modo che $numeri sia un array vuoto<br />
$numeri = array();<br />
//Aggiungo i valori <br />
$numeri[] = 1;  //Chiave vale (int)0<br />
$numeri[] = 2;  //Chiave vale (int)1<br />
$numeri[] = 4;  //Chiave vale (int)2<br />
$numeri[] = 8;  //...<br />
$numeri[] = 16;<br />
$numeri[] = 32;<br />
EOT;
            //Faccio in modo che $numeri sia un array vuoto
            $numeri = array();
            //Aggiungo i valori
            $numeri[] = 1;  //Chiave vale (int)0
            $numeri[] = 2;  //Chiave vale (int)1
            $numeri[] = 4;  //Chiave vale (int)2
            $numeri[] = 8;  //...
            $numeri[] = 16;
            $numeri[] = 32;
            var_dump($numeri);          
         
            echo '<h3>Inizializzazione di un array con chiavi numeriche che iniziano da un valore definito</h3>';
            echo <<<'EOT'
//Faccio in modo che $numeri sia un array vuoto<br />
$numeri = array();<br />
//Aggiungo i valori <br />
$numeri[1] = 2;  //Chiave vale (int)1<br />
$numeri[] = 4;  //Chiave vale (int)2<br />
$numeri[] = 8;  //...<br />
$numeri[] = 16;<br />
$numeri[] = 32;<br />
EOT;
            //Faccio in modo che $numeri sia un array vuoto
            $numeri = array();
            //Aggiungo i valori        
            $numeri[1] = 2;  //Chiave vale (int)1
            $numeri[] = 4;  //Chiave vale (int)2
            $numeri[] = 8;  //...
            $numeri[] = 16;
            $numeri[] = 32;
            var_dump($numeri);
         
            echo '<h3>Estensione dinamica di un array</h3>';
            echo <<<'EOT'
//Definisco un array con un solo valore<br />
$numeri = array(1=>2);<br />
EOT;
            //Definisco un array con un solo valore
            $numeri = array(1=>2);
            var_dump($numeri);
            echo <<<'EOT'
//Estendo dinamicamente l'array con nuove coppie chiave=>valore<br />
//in cui la chiave è generata automaticamente da PHP ed il valore<br />
//è calcolato sul valore dell'ultimo elemento inserito<br />
for( $i=2; $i<=10; $i++)<br />
&nbsp&nbsp&nbsp&nbsp$numeri[] = $numeri[$i-1]*2;<br />
EOT;
            //Estendo dinamicamente l'array con nuove coppie chiave=>valore
            //in cui la chiave è generata automaticamente da PHP ed il valore
            //è calcolato sul valore dell'ultimo elemento inserito
            for( $i=2; $i<=10; $i++)
                $numeri[] = $numeri[$i-1]*2;
            var_dump($numeri);
            echo '<hr />';
         
            echo '<h3>Inizializzazione tramite copia</h3>';
            echo <<<'EOT'
$numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);<br />
$mioArray = $numeri;<br />
$numeri[0] = 2048;<br />
EOT;
            $numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
            $mioArray = $numeri;
            $numeri[0] = 2048;
            var_dump($numeri,$mioArray);
            echo '<hr>';
         
            echo '<h3>Inizializzazione tramite riferimento</h3>';
            echo <<<'EOT'
$numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);<br />
$mioArray = &$numeri;<br />
$numeri[0] = 2048;<br />
EOT;
            $numeri = array( 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
            $mioArray = &$numeri;
            $numeri[0] = 2048;
            var_dump($numeri,$mioArray);
        ?>
    </body>
</html>