venerdì 20 aprile 2012

Introduzione al PHP: Tipi di Dato Primitivi

Il linguaggio di programmazione PHP non è a tipizzazione forte, il che significa che tutte le variabili non hanno bisogno di essere dichiarate prima di poter essere utilizzate e nel momento in cui le si utilizza possono contenere qualunque tipo di dato. Ciò significa che se desideriamo utilizzare una variabile ci basta inizializzarla, per esempio:
$eta=25;

In tal modo si dice all'interprete PHP che una variabile chiamata “$eta” esiste, contiene un dato numerico, e ha un valore iniziale di “25”. Il valore assegnato ad una variabile determina il tipo primitivo della variabile. In qualunque momento è però possibile assegnare ad una variabile esistente un valore del tutto diverso causando una modifica del tipo primitivo utilizzato per la memorizzazione del dato.  Gli otto tipi primitivi supportati al linguaggio di programmazione PHP sono:
  • int o integer: Il tipo di dato int è un intero con segno in complemento a due. Il valore minimo e massimo dipendono dalla piattaforma sebbene di norma siano utilizzati 32 bit (4 Bytes). Architetture a 64 bit possono utilizzare 64 bit (8 Bytes) per la rappresentazione del numero.  La dimensione in Bytes occupata per un numero int si ottiene dalla constante predefinita PHP_INT_SIZE. Valore minimo e valore massimo ammessi sono ottenibili tramite la costante predefinita PHP_INT_MAX:

    $massimoIntero = PHP_INT_MAX;
    $minimoIntero = -PHP_INT_MAX - 1;


    Nel caso di rappresentazione a 32 bit, ha un valore minimo di -2.147.483.648 e un massimo di 2.147.483.647 (inclusi).
    Qualora il dato ecceda i valori minimo (underflow) o massimo (overflow) PHP memorizzerà l'intero in un tipo primitivo double cambiando automaticamente il tipo primitivo utilizzato dalla variabile. Qualora si forzi il tipo ad int tramite un'operazione di cast  si avrà un comportamento ciclico in cui il valore successivo al massimo possibile è il minimo possibile e il valore precedente il minimo possibile è il massimo.

    //Dopo questa istruzione $overflow contiene -2147483648
    //se PHP_INT_SIZE vale 4 (Bytes) ossia 32 bit
    $overflow = (int)(PHP_INT_MAX + 1);
    Ciclicità numerica in caso di valori in overflow
    cui sia applicato il cast al tipo int
  • float o double: Il tipo di dato double è un IEEE754 in virgola mobile. La dimensione in bit dipende dal sistema, sebbene un valore massimo di circa 1.8e308 con una precisione approssimativa di 14 cifre decimali sia un valore possibile (formato IEEE a 64 bit). Questo tipo di dato non dovrebbe mai essere utilizzato per valori precisi, come la valuta. Per questo, hai bisogno di utilizzare le funzioni BC (Binary Calculator - tutte le funzioni bc iniziano con queste due consonanti) che supportano numeri di qualunque dimensione e precisione rappresentati come stringhe. In alternativa è possibile utilizzare le funzioni GMP (tratte dalla libreria GNU Multiple Precision - i nomi delle funzioni iniziano con gmp_) per la memorizzazione di interi di grandezza arbitraria.
  • boolean: Il tipo di dato boolean ha solo due valori possibili: true e false.  I due valori sono parole chiave del linguaggio e sono case-insesitive, quindi possono essere scritte indifferentemente maiuscole o minuscole. L'utilizzo di variabili con valore primitivo boolean è consigliato per semplici flag che tracciano la condizione vero/falso e nelle strutture di controllo
  • string: Il tipo di dato string è una serie di byte, ognuno dei quali rappresenta un carattere, più un intero che indica la dimensione complessiva della stringa. Ciò significa che PHP memorizza caratteri a 8 bit quindi, un insieme di 256 possibili caratteri, senza che sia applicata una codifica specifica. Ne consegue che PHP non offre supporto nativo per Unicode. Una stringa può contenere fino a 2GB di caratteri (l'intero che ne indica la lunghezza). Non essendo specificata una codifica nativa per PHP la codifica utilizzata è quella del file di script (in NetBeans fin'ora abbiamo utilizzato UTF-8 ma può essere cambiata).
    L'encoding utilizzato da NetBeans per i file sorgente PHP
    e che si riflette sulle stringhe PHP
    Quindi nella stringa ogni carattere potrà occupare da 1 a 4 byte, ma occorre fare attenzione all'uso di alcune funzioni, che si aspettano un byte per carattere. Seguirà un post di approfondimento sulla codifica dei caratteri in PHP.
  • array: Il tipo di dato array in PHP non è da intendersi nel modo classico dei linguaggi di programmazione. E' una mappa ordinata che crea un'associazione chiave<->valore. La chiave può essere di tipo int o string, mentre il valore può essere di qualunque tipo, compreso un array. I valori contenuti nell'array non devono essere omogenei, ma ogni elemento può essere di tipo diverso. Anche le chiavi non devono essere necessariamente tutte dello stesso tipo, ma si possono mescolare nel medesimo array chiavi numeriche con chiavi stringa. Il tipo numerico però prevale sul tipo stringa, nel senso che indicando:
    $vettore["3"]="Hello World";
    la chiave "3" non è memorizzata come string ma come int, purché non ci sia perdita d'informazione. Infatti se scriviamo:
    $vettore["03"]="Hello World";
    la chiave viene memorizzata come string altrimenti lo 0 nella combinazione 03 andrebbe perso.
  • object: Il tipo object è un puntatore ad una locazione di memoria allocata per l'istanza di una classe per mezzo dell'istruzione new.
  • resource: Il tipo di dato resource contiene un riferimento a risorse esterne (file aperti, connessioni a DB, ecc.) ottenute tramite chiamate a funzioni speciali.
  • NULL: Il tipo NULL ammette un unico valore che è appunto NULL (è case-insensitive, quindi può essere scritto anche null) che rende una variabile, sebbene esistente, priva di valore. Per sapere se una variabile non ha valore, ossia le è stato assegnato valore null, si utilizza l'apposita funzione is_null($nomeVariabile)
Codice di DemoTipiPrimitivi per testare alcune caratteristiche di alcuni tipi. Per utilizzarlo crea un nuovo progetto in NetBeans e sostituisci il contenuto di index.php con il codice seguente:

Output prodotto



<?php
interface Demo{
    /**
     *Metodo di esecuzione del test
     *@return string l'output prodotto dall'esecuzione del test 
     */
    public static function esegui();
}

/**
 * Classe di implementazione dell'interfaccia Demo per l'esecuzione
 * di test su numeri interi 
 */
class DemoInt implements Demo{    
    public static function esegui(){
        //Fase di inizializzazione delle varaibili locali al metodo
        //Recupero massimo numero intero possibile
        $massimoIntero=PHP_INT_MAX;
        $tipoPrimitivoMassimoIntero=gettype($massimoIntero);
        
        //Calcolo minimo intero possible
        $minimoIntero=-PHP_INT_MAX-1;
        $tipoPrimitivoMinimoIntero=gettype($minimoIntero);
        
        //Gestione dell'overflow
        $overflowIntero=$massimoIntero+1;
        $tipoPrimitivoOverflowIntero=gettype($overflowIntero);
        
        //Gestione dell'underflow
        $underflowIntero=$minimoIntero-1;
        $tipoPrimitivoUnderflowIntero=gettype($underflowIntero);
        
        //Overflow con cast
        $castOverflowIntero=(int)($massimoIntero+1);
        $tipoPrimitivoCastOverflowIntero=gettype($castOverflowIntero);
        
        //Underflow con cast
        $castUnderflowIntero=(int)($minimoIntero-1);
        $tipoPrimitivoCastUnderflowIntero=gettype($castUnderflowIntero);
        
        //dimensione del tipo int
        $dimensioneInteri=PHP_INT_SIZE;
                
        //Produzione dell'output da ritornare e uso
        //delle variabili locali
        $messaggio = "<h2>Test sui numeri Interi</h2>";
        $messaggio .= "<pre>";
        $messaggio .= "Dimensione Interi : $dimensioneInteri Bytes ".PHP_EOL;        
        $messaggio .= "Massimo Intero    : $massimoIntero  - Tipo Primitivo: $tipoPrimitivoMassimoIntero ".PHP_EOL;
        $messaggio .= "Valore Minimo     : $minimoIntero - Tipo Primitivo: $tipoPrimitivoMinimoIntero ".PHP_EOL;
        $messaggio .= "Valore Intero in Overflow  : $overflowIntero  - Tipo Primitivo: $tipoPrimitivoOverflowIntero ".PHP_EOL;
        $messaggio .= "Valore Intero in Underflow : $underflowIntero - Tipo Primitivo: $tipoPrimitivoUnderflowIntero ".PHP_EOL;
        $messaggio .= "Cast a int del Valore Intero in Overflow   : $castOverflowIntero - Tipo Primitivo: $tipoPrimitivoCastOverflowIntero ".PHP_EOL;
        $messaggio .= "Cast a int del Valore Interno in Underflow : $castUnderflowIntero  - Tipo Primitivo: $tipoPrimitivoCastUnderflowIntero ".PHP_EOL;
        $messaggio .= "</pre><hr/>";        
        
        return $messaggio;
    } 
}

class DemoDouble implements Demo{
    public static function esegui() {
        //Inizializzazione varibili
        $valoreA=1.23456789;
        $valoreB=1.23456780;
        
        //Esecuzione dei calcoli
        $differenza = $valoreA-$valoreB;
        $epsilon= 0.00000009;
        
        //Produzionedel testo esplicativo
        $messaggio = "<h2>Test sulla precisione dei double</h2>";
        $messaggio .= "<pre>";
        $messaggio .= "Valore A : $valoreA\n";
        $messaggio .= "Valore B : $valoreB\n";
        $messaggio .= "A - B    : $differenza\n";
        $messaggio .= "epsilon  : $epsilon\n"; 
        $messaggio .= ($differenza==$epsilon)?"I valori epsilon e A-B sono uguali":"I epsilon e A-B sono diversi";
        $messaggio .= "</pre><hr/>";
        return $messaggio;
    }
}

class DemoString implements Demo{
    public static function esegui() {
        //Inizializzazione varibili
        $stringa="ABC";
        $lunghezzaStringa =  strlen($stringa);
        
        $stringa2="ABCÂÃÄ";
        $lunghezzaStringa2=  strlen($stringa2);
        
        //Produzione dei risultati
        $messaggio = "<h2>Test sulle stringhe</h2>";
        $messaggio .= "<pre>";
        $messaggio .= "Stringa di prova : $stringa".PHP_EOL;
        $messaggio .= "Lunghezza        : $lunghezzaStringa".PHP_EOL;
        $messaggio .= "Stringa2 di prova: $stringa2".PHP_EOL;
        $messaggio .= "Lunghezza        : $lunghezzaStringa2".PHP_EOL.PHP_EOL;
        $messaggio .= "Sebbene siano due stringhe di 3 e 6 caratteri, i 6 caratteri\n";
        $messaggio .= "della seconda stringa richiedono 3 byte per i primi 3 e 6\n";
        $messaggio .= "byte per i successivi 3 per codificarli in UTF-8 (encoding del file sorgente)\n";
        $messaggio .= "Essendo le stringhe degli array di byte, la funzione strlen()\n";
        $messaggio .= "ritorna il numero di byte occupati dalla stringa";
        $messaggio .= "</pre><hr/>";
        
        return $messaggio;
    }
}

class DemoNULL implements Demo{
    public static function esegui() {
        //inizializzazione
        $null=null;
        $bool=false;
        
        //produzione dei risultati
        $messaggio = "<h2>Test sul tipo NULL</h2>";
        $messaggio .= "<pre>";
        $messaggio .= "L'utilizzo di is_null() è l'unico modo per testare se una \n";
        $messaggio .= "variabile è NULL:\n";        
        $messaggio .= "\$null==NULL è ".(($null==null)?"true\n":"false\n");
        $messaggio .= "\$bool==NULL è ".(($bool==null)?"true\n":"false\n");
        $messaggio .= "is_null(\$null) è ".((is_null($null))?"true\n":"false\n");
        $messaggio .= "is_null(\$bool) è ".((is_null($bool))?"true\n":"false\n");
        $messaggio .= "Tipo di \$null : ".gettype($null).PHP_EOL;
        $messaggio .= "Tipo di \$bool : ".gettype($bool).PHP_EOL;
        $messaggio .= "</pre>";
        
        return $messaggio;
    }
}

?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Test sui Tipi Primitivi</title>
    </head>
    <body>
        <h1>Esecuzione dei test sui tipi di dato primitivo</h1>
        <?php
        echo DemoInt::esegui();
        echo DemoDouble::esegui();
        echo DemoString::esegui();
        echo DemoNULL::esegui();
        ?>
    </body>
</html>