3. Le basi di PHP
3.1. La struttura delle directory degli script

3.2. Configurazione di PHP
PHP viene fornito preconfigurato tramite un file di testo [php.ini]. Tutte queste impostazioni possono essere modificate a livello di programmazione. La configurazione di PHP influenza notevolmente l'esecuzione degli script. È quindi importante comprenderla. Il seguente script [phpinfo.php] consente di farlo:
Commenti
- riga 3: la funzione [phpinfo] visualizza la configurazione di PHP;
Risultati dell'esecuzione
La funzione [phpinfo] visualizza qui oltre 800 righe di configurazione. Non le commenteremo perché la maggior parte riguarda l'uso avanzato di PHP. Una riga importante è la riga 13 sopra: indica quale file [php.ini] è stato utilizzato per configurare il PHP che userai per eseguire i tuoi script. Se vuoi modificare la configurazione di runtime di PHP, questo è il file che devi modificare. In questo file ci sono molti commenti che spiegano il ruolo delle varie impostazioni.
3.3. Un primo esempio
3.3.1. Il codice
Di seguito è riportato un programma [bases-01.php] che illustra le funzionalità di base di PHP.
<?php
// this is a comment
// variable used without being declared
$nom = "dupont";
// a screen display
print "nom=$nom\n";
// an array with elements of different types
$tableau = array("un", "deux", 3, 4);
// its number of elements
$n = count($tableau);
// a loop
for ($i = 0; $i < $n; $i++) {
print "tableau[$i]=$tableau[$i]\n";
}
// initialize 2 variables with the contents of an array
list($chaine1, $chaine2) = array("chaine1", "chaine2");
// concatenation of the 2 strings
$chaine3 = $chaine1 . $chaine2;
// result display
print "[$chaine1,$chaine2,$chaine3]\n";
// use function
affiche($chaine1);
// the type of a variable can be known
afficheType("n", $n);
afficheType("chaine1", $chaine1);
afficheType("tableau", $tableau);
// the type of a variable can change at runtime
$n = "a changé";
afficheType("n", $n);
// a function can return a result
$res1 = f1(4);
print "res1=$res1\n";
// a function can render a table of values
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
// we could have retrieved these values in a table
$t = f2();
for ($i = 0; $i < count($t); $i++) {
print "t[$i]=$t[$i]\n";
}
// testing
for ($i = 0; $i < count($t); $i++) {
// displays only channels
if (getType($t[$i]) === "string") {
print "t[$i]=$t[$i]\n";
}
}
// == and === comparison operators
if("2"==2){
print "avec l'opérateur ==, la chaîne 2 est égale à l'entier 2\n";
}else{
print "avec l'opérateur ==, la chaîne 2 n'est pas égale à l'entier 2\n";
}
if("2"===2){
print "avec l'opérateur ===, la chaîne 2 est égale à l'entier 2\n";
}
else{
print "avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2\n";
}
// other tests
for ($i = 0; $i < count($t); $i++) {
// displays only integers >10
if (getType($t[$i]) === "integer" and $t[$i] > 10) {
print "t[$i]=$t[$i]\n";
}
}
// a while loop
$t = [8, 5, 0, -2, 3, 4];
$i = 0;
$somme = 0;
while ($i < count($t) and $t[$i] > 0) {
print "t[$i]=$t[$i]\n";
$somme += $t[$i]; //$somme=$somme+$t[$i]
$i++; //$i=$i+1
}//while
print "somme=$somme\n";
// end of program
exit;
//----------------------------------
function affiche($chaine) {
// displays $chaine
print "chaine=$chaine\n";
}
//poster
//----------------------------------
function afficheType($name, $variable) {
// displays the type of $variable
print "type[variable $" . $name . "]=" . getType($variable) . "\n";
}
//afficheType
//----------------------------------
function f1($param) {
// adds 10 to $param
return $param + 10;
}
//----------------------------------
function f2() {
// returns 3 values
return array("un", 0, 100);
}
?>
I risultati:
nom=dupont
tableau[0]=un
tableau[1]=deux
tableau[2]=3
tableau[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[variable $n]=integer
type[variable $chaine1]=string
type[variable $tableau]=array
type[variable $n]=string
res1=14
(res1,res2,res3)=[un,0,100]
t[0]=un
t[1]=0
t[2]=100
t[0]=un
avec l'opérateur ==, la chaîne 2 est égale à l'entier 2
avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2
t[2]=100
t[0]=8
t[1]=5
somme=13
Commenti
- riga 5: In PHP, non si dichiarano i tipi delle variabili. Le variabili hanno un tipo dinamico che può cambiare nel tempo. $name rappresenta la variabile con l'identificatore name;
- riga 7: per visualizzare l'output sullo schermo, è possibile utilizzare l'istruzione print o l'istruzione echo;
- riga 9: la parola chiave array viene utilizzata per definire un array. La variabile $name[$i] rappresenta l'$i-esimo elemento dell'array $array;
- riga 11: la funzione count($tableau) restituisce il numero di elementi nell'array $tableau;
- righe 13–15: un ciclo. Poiché questo ciclo contiene una sola istruzione, le parentesi graffe sono facoltative. Nel resto di questo documento, useremo sempre le parentesi graffe indipendentemente dal numero di istruzioni;
- riga 14: le stringhe sono racchiuse tra virgolette doppie " o virgolette singole '. All'interno delle virgolette doppie, le variabili $variable vengono valutate, ma non all'interno delle virgolette singole;
- riga 17: la funzione list permette di raggruppare le variabili in una lista e di assegnare loro un valore con una singola operazione di assegnazione. Qui, $chaine1="chaine1" e $chaine2="chaine2";
- riga 19: l'operatore . è l'operatore di concatenazione delle stringhe;
- righe 83–86: la parola chiave `function` definisce una funzione. Una funzione può restituire o meno valori utilizzando l'istruzione `return`. Il codice chiamante può ignorare o recuperare i risultati di una funzione. Una funzione può essere definita in qualsiasi punto del codice.
- riga 92: la funzione predefinita getType($variable) restituisce una stringa che rappresenta il tipo di $variable. Questo tipo può cambiare nel tempo;
- Riga 45: l'operatore === esegue un confronto rigoroso tra due elementi: per essere confrontati, devono essere dello stesso tipo. L'operatore == è meno rigoroso: due elementi possono essere uguali senza essere dello stesso tipo. Ciò è dimostrato dalle istruzioni alle righe 50–60. Nel caso dell'operatore ==, il confronto viene eseguito dopo aver convertito entrambi gli elementi da confrontare nello stesso tipo. Avvengono quindi delle conversioni implicite. È piuttosto facile “dimenticarsi” di queste conversioni implicite e finire così con risultati inaspettati, come scoprire che una condizione è vera quando ci si aspettava che fosse falsa. Per evitare questa insidia, useremo sistematicamente l'operatore di confronto ===;
- riga 64: è possibile utilizzare anche gli operatori booleani or e !;
- riga 69: invece della notazione array(), in PHP 7 è possibile utilizzare la notazione [] per inizializzare un array;
- riga 80: la funzione predefinita exit interrompe l'esecuzione dello script;
- riga 107: il tag ?> segna la fine dello script PHP. Non è essenziale. Inoltre, in un contesto web, può causare problemi se seguito da spazi o interruzioni di riga, che sono difficili da rilevare perché non sono visibili in un editor di testo. Pertanto, nel resto di questo documento, ometteremo sistematicamente questo tag;
Nota: in questo documento useremo la parola chiave [print] per visualizzare il testo sulla console. Un altro modo per ottenere lo stesso risultato è usare la parola chiave [echo]. Esistono sottili differenze tra queste due parole chiave, ma nel contesto di questo documento non ce ne saranno. Quindi, se preferisci usare [echo], fallo pure.
3.3.2. Utilizzo di NetBeans
NetBeans emette vari avvisi che vale la pena controllare. Prendiamo l'esempio dello script [bases-01.php]:

Alla riga 5, NetBeans emette un avviso che il file non è conforme alla raccomandazione PSR-1 (PHP Standard Recommendations No. 1). Le PSR sono raccomandazioni per la produzione di codice standard al fine di facilitare l'interoperabilità e la manutenzione del codice scritto da persone diverse. Può essere fastidioso ricevere avvisi se si desidera violare deliberatamente gli standard, ad esempio perché il team di progetto ne ha di diversi. È possibile configurare ciò che si desidera controllare o meno con NetBeans:

- in [5], troverai gli elementi che desideri controllare con NetBeans;
- in [6], il livello di gravità assegnato all'errore segnalato da NetBeans;

In [7] è possibile notare che abbiamo richiesto di verificare che il codice segua le raccomandazioni PSR-0 e PSR-1. Nulla è obbligatorio. Durante l'apprendimento del linguaggio, è consigliabile verificare il maggior numero possibile di opzioni offerte da NetBeans. In questo modo imparerete molto. Potrete poi adattare questi controlli di NetBeans agli standard di codifica del vostro team di progetto.
Diamo un'occhiata agli standard di codifica PSR-1 [8, 9]:
Opzione | Controllo |
| Le costanti di classe DEVONO essere dichiarate interamente in maiuscolo con separatori di tipo trattino basso. Es.: const TAUX_TVA |
| I nomi dei metodi DEVONO essere dichiarati in camelCase(). Es.: public function executeBatchTaxes{} |
| I nomi delle proprietà DOVREBBERO essere dichiarati nei formati $StudlyCaps, $camelCase o $under_score (in modo coerente all'interno di un ambito) Es.: public AnnualSalary (StudlyCaps), public annualSalary (camelCase), public annual_salary (underscore) |
| Un file DOVREBBE dichiarare nuovi simboli e non causare altri effetti collaterali, oppure DOVREBBE eseguire logica con effetti collaterali, ma NON DOVREBBE fare entrambe le cose. |
| I nomi dei tipi DEVONO essere dichiarati in StudlyCaps (il codice scritto per la versione 5.2.x e precedenti DOVREBBE utilizzare la convenzione di pseudonamespacing dei prefissi Vendor_ sui nomi dei tipi). Ogni tipo si trova nel proprio file ed è in uno spazio dei nomi di almeno un livello: un nome di fornitore di primo livello. Es: class ScholarshipStudent {} |
La raccomandazione PSR-1/4 stabilisce che un file PHP deve contenere:
- una dichiarazione di tipo (classi, interfacce);
- oppure codice eseguibile senza dichiarazioni di nuovi tipi;
Esistono altre raccomandazioni PHP non applicate da NetBeans: PSR-3, PSR-4, PSR-6, PSR-7 e PSR-13.
Per semplicità, non tutti gli esempi in questo documento aderiscono alla raccomandazione PSR-1, poiché ciò richiederebbe la suddivisione del codice di classi e interfacce in file separati, il che è troppo macchinoso per esempi di base. È quindi più facile mettere tutto in un unico file. Per l'applicazione di esempio presentata come tema centrale di questo documento, abbiamo cercato di seguire la raccomandazione PSR-1 il più fedelmente possibile.
Alcuni avvisi di NetBeans indicano un potenziale errore:

L'avviso [Variabili non inizializzate] indica un probabile errore, spesso un errore di battitura nel nome di una variabile. Lo stesso vale per l'avviso [Variabili inutilizzate].
Infine, si consiglia di controllare tutti gli avvisi di NetBeans, indicati da un banner nel margine sinistro del codice e da un trattino giallo nel margine destro:


3.4. Ambito delle variabili
3.4.1. Esempio 1
Lo script [bases-02.php] è il seguente:
<?php
// variable scope
function f1() {
// we use the global variable $i
global $i;
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// we use the global variable $i
global $i;
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
// we use a local variable $i
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0; // these two variables are known only to a function f
// only if it explicitly declares with the global instruction
// she wants to use them
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
I risultati:
Commenti
- Righe 29–30: definiscono due variabili, $i e $j, nel programma principale. Queste variabili non sono note all'interno delle funzioni. Pertanto, alla riga 9, la variabile $j nella funzione f1 è una variabile locale della funzione f1 ed è diversa dalla variabile $j nel programma principale. Una funzione può accedere a una variabile $variable nel programma principale utilizzando la parola chiave global;
- alla riga 7, l'istruzione fa riferimento alla variabile globale $i del programma principale;
3.4.2. Esempio 3
Lo script [bases-03.php] è il seguente:
<?php
// the scope of a variable is global to code blocks
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
I risultati:
Commenti
In alcuni linguaggi, una variabile definita all'interno di parentesi graffe ha un ambito limitato a tali parentesi: non è visibile al di fuori di esse. I risultati sopra riportati mostrano che questo non è il caso in PHP. La variabile $i definita alla riga 5 all'interno delle parentesi graffe è la stessa di quella utilizzata alle righe 4 e 8 al di fuori di esse.
3.5. Cambiamenti di tipo
Le variabili in PHP non hanno un tipo fisso. Il loro tipo può cambiare durante l'esecuzione a seconda del valore assegnato alla variabile. Nelle operazioni che coinvolgono dati di vari tipi, l'interprete PHP esegue conversioni implicite per portare gli operandi a un tipo comune. Queste conversioni implicite, se sconosciute allo sviluppatore, possono essere fonte di errori difficili da individuare. Di seguito è riportato uno script [bases-04.php] che mostra le conversioni implicite ed esplicite:
<?php
// strict types for passing parameters
declare(strict_types=1);
// implicit type changes
// type -->bool
print "Conversion vers un booléen------------------------------\n";
showBool("abcd", "abcd");
showBool("", "");
showBool("[1, 2, 3]", [1, 2, 3]);
showBool("[]", []);
showBool("NULL", NULL);
showBool("0.0", 0.0);
showBool("0", 0);
showBool("4.6", 4.6);
function showBool(string $prefixe, $var) : void {
print "(bool) $prefixe : ";
// conversion of $var to Boolean is automatic in the following test
if ($var) {
print "true";
} else {
print "false";
}
print "\n";
}
Commenti
- riga 4: richiede un controllo rigoroso dei tipi dei parametri di una funzione quando specificato;
- riga 18: la funzione [showBool] ha lo scopo di dimostrare la conversione implicita (automatica) eseguita dall'interprete PHP quando un valore di qualsiasi tipo deve essere convertito in un valore booleano (riga 21);
- riga 18: al parametro $var non è assegnato alcun tipo. Il parametro effettivo può quindi essere di qualsiasi tipo. Il parametro $prefix, invece, deve essere di tipo stringa. La funzione showBool non restituisce alcun valore (void);
- riga 21: nell'istruzione if($var), il valore di $var deve essere convertito in un valore booleano affinché l'if venga valutato. Sorprendentemente, l'interprete PHP ha una soluzione per qualsiasi tipo di valore che gli viene fornito;
- righe 9–16: il valore del parametro della funzione [showBool] sarà, a sua volta:
- riga 9: una stringa non vuota: risultato TRUE (le maiuscole non contano, TRUE=true);
- riga 10: una stringa vuota: risultato FALSE;
- riga 11: un array non vuoto: risultato TRUE;
- riga 12: un array vuoto: risultato FALSE;
- riga 14: il numero reale 0: risultato FALSE;
- riga 15: il numero intero 0: risultato FALSE;
- riga 16: un numero reale (o intero) diverso da 0: risultato TRUE;
Ecco cosa mostra lo schermo:
Conversion vers un booléen------------------------------
(bool) abcd : true
(bool) : false
(bool) [1, 2, 3] : true
(bool) [] : false
(bool) NULL : false
(bool) 0.0 : false
(bool) 0 : false
(bool) 4.6 : true
Continuiamo con il codice dello script:
//
// implicit changes from string type to numeric type
// string --> number
print "Conversion chaîne vers nombre------------------------------\n";
showNumber("12");
showNumber("45.67");
showNumber("abcd");
function showNumber(string $var) : void {
$nombre = $var + 1;
var_dump($nombre);
print "($var): $nombre\n";
}
Commenti
- riga 9: la funzione [showNumber] accetta un parametro di tipo stringa e non restituisce alcun risultato (void);
- riga 10: questo parametro viene utilizzato in un'operazione aritmetica, il che costringerà l'interprete PHP a tentare di convertire $var in un numero;
- riga 5: convertirà la stringa “12” nel numero intero 12;
- riga 6: convertirà la stringa “45.67” nel numero in virgola mobile 45.67;
- riga 7: emetterà un avviso ma convertirà comunque la stringa “abcd” nel numero 0;
Ecco i risultati dell'esecuzione:
Continuiamo con il codice dello script:
// changements explicites de type
// vers int
showInt("12.45");
showInt(67.8);
showInt(TRUE);
showInt(NULL);
function showInt($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((int) $var);
print "\n";
}
Commenti
- Riga 21: La funzione [showInt] accetta un parametro di qualsiasi tipo e non restituisce alcun risultato. Alla riga 26 tenta di convertire il parametro $var in un numero intero. In generale, per convertire una variabile $var nel tipo T, si scrive (T) $var, dove T può essere: int, integer, bool, boolean, float, double, real, string, array, object, unset;
- riga 16: converte la stringa “12.45” nel numero intero 12;
- riga 17: converte il numero reale 67.8 nel numero intero 67;
- riga 18: converte il valore booleano TRUE nell'intero 1 (il valore booleano FALSE nell'intero 0);
- riga 19: converte il puntatore NULL nell'intero 0;
Ecco cosa viene visualizzato sullo schermo:
Continuiamo lo studio dello script con la conversione esplicita dei valori nel tipo float:
// to float
showFloat("12.45");
showFloat(67);
showFloat(TRUE);
showFloat(NULL);
function showFloat($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((float) $var);
print "\n";
}
Commenti
- riga 35: la funzione [showFloat] accetta un parametro di qualsiasi tipo e non restituisce alcun risultato;
- riga 40: il valore di questo parametro viene esplicitamente convertito in un float;
- riga 30: la stringa “12.45” viene convertita nel numero in virgola mobile 12.45;
- riga 31: l'intero 67 viene convertito nel numero reale 67;
- riga 32: il valore booleano TRUE viene convertito nel numero reale 1 (il valore FALSE nel numero 0);
- riga 33: il puntatore NULL viene convertito nel numero reale 0;
Ciò è dimostrato dall'output sullo schermo:
Continuiamo la panoramica dello script esaminando le conversioni al tipo stringa:
// to string
showstring(5);
showString(6.7);
showString(FALSE);
showString(NULL);
function showString($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((string) $var);
print "\n";
}
- riga 49: la funzione [showString] accetta un parametro di qualsiasi tipo e non restituisce alcun risultato;
- riga 54: il valore del parametro viene convertito in una stringa;
- riga 44: il numero intero 5 verrà convertito nella stringa "5";
- riga 45: il numero in virgola mobile 6.7 verrà convertito nella stringa "6.7";
- riga 46: il valore booleano FALSE verrà convertito in una stringa vuota;
- riga 47: il puntatore NULL viene convertito in una stringa vuota;
Ecco i risultati sullo schermo:
3.6. Array
3.6.1. Array classici unidimensionali
Lo script [bases-05.php] è il seguente:
<?php
// classic paintings
// initialization
$tab1 = array(0, 1, 2, 3, 4, 5);
// routes - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// routes - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1)) {
print "tab1[$clé]=$valeur\n";
}
// add elements
$tab1[] = $i++;
$tab1[] = $i++;
// routes - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
// delete last item
array_pop($tab1);
// routes - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// delete first element
array_shift($tab1);
// routes - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// addition at end of table
array_push($tab1, -2);
// routes - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// addition at the beginning of the table
array_unshift($tab1, -1);
// routes - 7
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
I risultati:
tab1 a 6 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 6 éléments
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_04.php on line 14
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 8 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=7
tab1 a 7 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1 a 6 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1 a 7 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1[6]=-2
tab1 a 8 éléments
tab1[0]=-1
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=-2
Commenti
Il programma sopra riportato illustra le operazioni per la manipolazione di un array di valori. In PHP esistono due notazioni per gli array:
L'array 1 è chiamato array, mentre l'array 2 è chiamato dizionario o array associativo, in cui gli elementi sono indicati come chiave => valore. La notazione $opposites["beautiful"] si riferisce al valore associato alla chiave "beautiful". In questo caso, tale valore è la stringa "ugly". L'array 1 è semplicemente una variante del dizionario e potrebbe essere scritto come:
Questo ci dà $array[2] = "three". In definitiva, si tratta sempre di dizionari. Nel caso di un array standard di n elementi, le chiavi sono i numeri interi nell'intervallo [0, n-1].
- riga 14: la funzione each($array) consente di iterare su un dizionario. Ad ogni chiamata, restituisce una coppia (chiave, valore) da esso. Come mostrato alla riga 10 dei risultati, la funzione each è ora deprecata in PHP 7;
- riga 13: la funzione reset($dictionary) imposta la funzione each sulla prima coppia (chiave, valore) nel dizionario.
- riga 14: il ciclo while si interrompe quando la funzione each restituisce una coppia vuota alla fine del dizionario. Qui è in atto una conversione implicita: la coppia vuota viene convertita nel valore booleano FALSE;
- riga 18: la notazione $array[]=value aggiunge l'elemento value come ultimo elemento di $array;
- riga 23: l'array viene iterato utilizzando un ciclo foreach. Questa sintassi consente di iterare su un dizionario — e quindi su un array — utilizzando due diverse sintassi:
La prima sintassi restituisce una coppia (chiave, valore) ad ogni iterazione, mentre la seconda restituisce solo l'elemento valore del dizionario.
- riga 28: la funzione array_pop($array) rimuove l'ultimo elemento da $array;
- riga 35: la funzione array_shift($array) rimuove il primo elemento da $array;
- riga 42: la funzione array_push($array,value) aggiunge value come ultimo elemento di $array;
- riga 49: la funzione array_unshift($array,value) aggiunge value come primo elemento di $array;
3.6.2. Il dizionario o array associativo
Lo script [bases-06.php] è il seguente:
<?php
// dictionaries
$conjoints = ["Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => ""];
// routes - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// dictionary sorting on key
ksort($conjoints);
// routes - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// list of dictionary keys
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++) {
print "clés[$i]=$clés[$i]\n";
}
// list of dictionary values
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++) {
print "valeurs[$i]=$valeurs[$i]\n";
}
// key search
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// deleting a key-value
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// end
exit;
function existe($conjoints, $mari) {
// checks whether the key $mari exists in the dictionary $conjoints
if (isset($conjoints[$mari])) {
print "La clé [$mari] existe associée à la valeur [$conjoints[$mari]]\n";
} else {
print "La clé [$mari] n'existe pas\n";
}
}
I risultati:
Nombre d'éléments du dictionnaire : 4
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_05.php on line 8
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
clés[0]=Jacques
clés[1]=Jean
clés[2]=Paul
clés[3]=Pierre
valeurs[0]=Lucette
valeurs[1]=
valeurs[2]=Virginie
valeurs[3]=Gisèle
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
conjoints[Jacques]=Lucette
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
Commenti
Il codice sopra riportato applica a un dizionario ciò che abbiamo visto in precedenza per un semplice array. Ci limiteremo a commentare le nuove funzionalità:
- riga 12: la funzione ksort (ordinamento per chiave) ordina un dizionario secondo l'ordine naturale delle chiavi;
- riga 19: la funzione array_keys($dictionary) restituisce l'elenco delle chiavi del dizionario sotto forma di array;
- riga 24: la funzione array_values($dictionary) restituisce l'elenco dei valori del dizionario sotto forma di array;
- riga 43: la funzione isset($variable) restituisce TRUE se $variable è stata definita, FALSE in caso contrario;
- riga 33: la funzione unset($variable) elimina la variabile $variable.
3.6.3. Array multidimensionali
Lo script [bases-07.php] è il seguente:
<?php
// classic multidimensional tables
// initialization
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// route
for ($i1 = 0; $i1 < count($multi); $i1++) {
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++) {
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
}
}
// multidimensional dictionaries
// initialization
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// route
foreach ($multi as $clé => $valeur) {
for ($i2 = 0; $i2 < count($valeur); $i2++) {
print "multi[$clé][$i2]=" . $multi[$clé][$i2] . "\n";
}
}
Risultati:
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi[zéro][0]=0
multi[zéro][1]=1
multi[zéro][2]=2
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
Commenti
- riga 5: gli elementi dell'array $multi sono essi stessi array;
- riga 14: l'array $multi diventa un dizionario (chiave, valore) in cui ogni valore è un array;
3.7. Stringhe
3.7.1. Notazione
Lo script [bases-08.php] è il seguente:
<?php
// string notation
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
Risultati:
3.7.2. Confronto
Lo script [bases-09.php] è il seguente:
<?php
// strict adherence to function parameter types
declare(strict_types=1);
// comparison function
function compareModele2Chaine(string $chaine1, string $chaine2): void {
// compare string1 and string2
if ($chaine1 === $chaine2) {
print "[$chaine1] est égal à [$chaine2]\n";
} else {
print "[$chaine1] est différent de [$chaine2]\n";
}
}
// string comparison tests
compareModele2Chaine("abcd", "abcd");
compareModele2Chaine("", "");
compareModele2Chaine("1", "");
exit;
Risultati:
[abcd] est égal à [abcd]
[] est égal à []
[1] est différent de []
Commenti
- Riga 9 del codice: avremmo potuto usare l'operatore == invece di ===. Quest'ultimo operatore è più restrittivo in quanto richiede che entrambi gli operandi siano dello stesso tipo. Si noti che in questo caso avrebbe potuto essere sostituito dall'operatore == poiché il tipo di entrambi i parametri è impostato su stringa nella firma della funzione;
3.7.3. Collegamenti tra stringhe e array
Lo script [bases-10.php] è il seguente:
<?php
// string to array
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
}
// table to string
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
// add an empty field
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // we now have 5 elements, the last being empty
// let's add another empty field
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // we now have 6 elements, the last two being empty
Risultati:
tab a 4 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
chaine2=1:2:3:4
chaîne=1:2:3:4:
tab a 5 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
chaîne=1:2:3:4::
tab a 6 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
tab[5]=
Commenti
- riga 5: la funzione explode($separator,$string) estrae i campi di $string separati da $separator. Pertanto, explode(":",$string) restituisce gli elementi di $string separati dalla stringa ":" sotto forma di array;
- riga 12: la funzione implode($separator,$array) esegue l'operazione inversa della funzione explode. Restituisce una stringa composta dagli elementi di $array separati da $separator;
3.7.4. Espressioni regolari
Lo script [bases-11.php] è il seguente:
<?php
// strict type for function parameters
declare (strict_types=1);
// regular expressions in php
// retrieve the various fields of a string
// the model: a sequence of numbers surrounded by any characters
// you only want to retrieve the sequence of digits
$modèle = "/(\d+)/";
// the chain is compared with the model
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// the model: a sequence of numbers surrounded by any characters
// we want the sequence of digits and the fields that follow and precede them
$modèle = "/^(.*?)(\d+)(.*?)$/";
// the chain is compared with the model
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// the template - a date in dd/mm/yy format
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
compareModele2Chaine($modèle, "10/05/97");
compareModele2Chaine($modèle, " 04/04/01 ");
compareModele2Chaine($modèle, "5/1/01");
// the model - a decimal number
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
compareModele2Chaine($modèle, "187.8");
compareModele2Chaine($modèle, "-0.6");
compareModele2Chaine($modèle, "4");
compareModele2Chaine($modèle, ".6");
compareModele2Chaine($modèle, "4.");
compareModele2Chaine($modèle, " + 4");
// end
exit;
// --------------------------------------------------------------------------
function compareModele2Chaine(string $modèle, string $chaîne): void {
// compares the $chaîne string with the $modèle model
// the chain is compared with the
$champs = [];
$correspond = preg_match($modèle, $chaîne, $champs);
// displaying results
print "\nRésultats($modèle,$chaîne)\n";
if ($correspond) {
for ($i = 0; $i < count($champs); $i++) {
print "champs[$i]=$champs[$i]\n";
}
} else {
print "La chaîne [$chaîne] ne correspond pas au modèle [$modèle]\n";
}
}
Risultati:
Résultats(/(\d+)/,xyz1234abcd)
champs[0]=1234
champs[1]=1234
Résultats(/(\d+)/,12 34)
champs[0]=12
champs[1]=12
Résultats(/(\d+)/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/(\d+)/]
Résultats(/^(.*?)(\d+)(.*?)$/,xyz1234abcd)
champs[0]=xyz1234abcd
champs[1]=xyz
champs[2]=1234
champs[3]=abcd
Résultats(/^(.*?)(\d+)(.*?)$/,12 34)
champs[0]=12 34
champs[1]=
champs[2]=12
champs[3]= 34
Résultats(/^(.*?)(\d+)(.*?)$/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/^(.*?)(\d+)(.*?)$/]
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,10/05/97)
champs[0]=10/05/97
champs[1]=10
champs[2]=05
champs[3]=97
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/, 04/04/01 )
champs[0]= 04/04/01
champs[1]=04
champs[2]=04
champs[3]=01
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,5/1/01)
La chaîne [5/1/01] ne correspond pas au modèle [/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/]
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,187.8)
champs[0]=187.8
champs[1]=
champs[2]=187.8
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,-0.6)
champs[0]=-0.6
champs[1]=-
champs[2]=0.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4)
champs[0]=4
champs[1]=
champs[2]=4
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,.6)
champs[0]=.6
champs[1]=
champs[2]=.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4.)
champs[0]=4.
champs[1]=
champs[2]=4.
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/, + 4)
champs[0]= + 4
champs[1]=+
champs[2]=4
Commenti
- Qui utilizziamo le espressioni regolari per estrarre vari campi da una stringa. Le espressioni regolari ci consentono di superare i limiti della funzione implode. Il principio consiste nel confrontare una stringa con un'altra stringa, detta pattern, utilizzando la funzione preg_match:
$correspond = preg_match($modèle, $chaîne, $champs);
La funzione preg_match restituisce un valore booleano TRUE se il modello è presente nella stringa. In tal caso, $fields[0] rappresenta la sottostringa che corrisponde al modello. Inoltre, se il modello contiene sottomodelli racchiusi tra parentesi, $fields[1] è la porzione di $string corrispondente al primo sottomodello, $fields[2] è la porzione di $string corrispondente al secondo sottomodello e così via...
Consideriamo il primo esempio. Il pattern è definito alla riga 10: indica una sequenza di una o più (+) cifre (\d) situate in qualsiasi punto della stringa. Inoltre, il pattern definisce un sottopattern racchiuso tra parentesi;
- Riga 12: Il pattern /(\d+)/ (una sequenza di una o più cifre in qualsiasi punto della stringa) viene confrontato con la stringa "xyz1234abcd". Si nota che la sottostringa 1234 corrisponde al pattern. Pertanto, $champs[0] sarà uguale a "1234". Inoltre, il pattern contiene sottopattern racchiusi tra parentesi. Avremo $champs[1]="1234";
- riga 13: il pattern /(\d+)/ viene confrontato con la stringa "12 34". Vediamo che le sottostringhe 12 e 34 corrispondono al pattern. Il confronto si ferma alla prima sottostringa che corrisponde al pattern. Pertanto, $champs[0]=12 e $champs[1]=12;
- riga 14: il pattern /(\d+)/ viene confrontato con la stringa "abcd". Non viene trovata alcuna corrispondenza;
Spieghiamo i pattern utilizzati nel resto del codice:
$modèle = "/^(.*?)(\d+)(.*?)$/";
corrisponde all'inizio della stringa (^), seguito da zero o più (*) caratteri arbitrari (.), poi una o più (+) cifre, seguite da zero o più (*) caratteri arbitrari (.). Il pattern (.*) corrisponde a zero o più caratteri arbitrari. Un pattern di questo tipo corrisponderà a qualsiasi stringa. Pertanto, il pattern /^(.*)(\d+)(.*)$/ non verrà mai trovato perché il primo sottopattern (.*) consumerà l'intera stringa. Il pattern (.*?)(\d+) indica 0 o più caratteri arbitrari fino al sottopattern successivo (?), in questo caso \d+. Pertanto, le cifre non vengono più catturate dal modello (.*). Il modello sopra riportato corrisponde quindi a [inizio della stringa (^), una sequenza di caratteri qualsiasi (.*?), una sequenza di una o più cifre (\d+), una sequenza di caratteri qualsiasi (.*?), fine della stringa ($)].
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
corrisponde a [inizio della stringa (^), 2 cifre (\d\d), il carattere / (\/), 2 cifre, /, 2 cifre, una sequenza di 0 o più spazi (\s*), fine della stringa ($)].
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
corrisponde all'inizio della stringa (^), 0 o più spazi (\s*), un segno + o - [+|-] che ricorre 0 o 1 volta (?), una sequenza di 0 o più spazi (\s*), una o più cifre seguite da un punto decimale seguito da zero o più cifre (\d+\.\d*) oppure (|) un punto decimale (\.) seguito da una o più cifre (\d+) oppure (|) una o più cifre (\d+), una sequenza di 0 o più spazi (\s*)].
Nota: il termine [spazio] nelle espressioni regolari si riferisce a un insieme di caratteri: spazi bianchi, nuova riga \n, tabulazione \t, ritorno a capo \r, avanzamento pagina \f…
3.8. Funzioni
3.8.1. Modalità di passaggio dei parametri
Lo script [base-12.php] è il seguente:
<?php
// function parameter step mode
// strict adherence to parameter type
declare(strict_types=1);
function f(int &$i, int $j): void {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0;
// $i and $j are passed to function f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
Risultati:
Commenti
Il codice sopra riportato illustra i due modi per passare parametri a una funzione. Si consideri il seguente esempio:
- riga 1: definisce i parametri formali $a e $b della funzione f. Questa funzione manipola questi due parametri formali e restituisce un risultato;
- riga 7: chiama la funzione f con due parametri effettivi $i e $j. Le relazioni tra i parametri formali ($a, $b) e i parametri effettivi ($i, $j) sono definite dalle righe 1 e 7:
- &$a: il simbolo & indica che il parametro formale $a assumerà il valore dell'indirizzo del parametro effettivo $i. In altre parole, $a e $i sono due riferimenti alla stessa posizione di memoria. Manipolare il parametro formale $a equivale a manipolare il parametro effettivo $i. Ciò è dimostrato dall'esecuzione del codice. Questa modalità di passaggio è adatta per i parametri di output e per grandi insiemi di dati come array e dizionari. Questa modalità di passaggio è chiamata pass-by-reference.
- $b: Il parametro formale $b assumerà il valore del parametro effettivo $j. Si tratta di un passaggio per valore. I parametri formali ed effettivi sono due variabili diverse. La manipolazione del parametro formale $b non ha alcun effetto sul parametro effettivo $j. Ciò è dimostrato dall'esecuzione del codice. Questa modalità di passaggio è adatta per i parametri di input.
- Consideriamo la funzione swap, che accetta due parametri formali $a e $b. La funzione scambia i valori di questi due parametri. Pertanto, durante una chiamata a swap($i,$j), il codice chiamante si aspetta che i valori dei due parametri effettivi vengano scambiati. Si tratta quindi di parametri di output (vengono modificati). Scriveremo quindi:
Il seguente script [base-13.php] mostra altri esempi:
<?php
// types in strict mode
// declare(strict_types = 1);
// parameter switching mode
function f(&$i, $j) {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
function g(int &$i, int $j) : void {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "g[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0;
// $i and $j are passed to function f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
// $i and $j are passed to function g
g($i, $j);
print "test[i,j]=[$i,$j]\n";
// pass incorrect parameters to f
$a=5.3;
$b=6.2;
f($a, $b);
print "test[a,b]=[$a,$b]\n";
// pass incorrect parameters to f
$a=5.3;
$b=6.2;
g($a, $b);
print "test[a,b]=[$a,$b]\n";
Commenti
- righe 8–14: la funzione f discussa nella sezione precedente, ma i parametri non sono tipizzati;
- righe 16–22: la funzione g fa la stessa cosa della funzione f, ma specifichiamo il tipo dei parametri attesi — questa è una nuova funzionalità di PHP 7. Ci aspettiamo due parametri di tipo int. Vogliamo vedere cosa succede quando il parametro effettivo passato alla funzione non ha il tipo previsto dalla funzione;
- righe 25–26: $i e $j sono due numeri interi;
- righe 28–29: chiamata alla funzione f con parametri del tipo previsto;
- righe 31–32: chiamata alla funzione g con parametri del tipo previsto;
- righe 34–35: le variabili $a e $b sono di tipo float;
- righe 36-37: chiamata alla funzione f con parametri che non sono del tipo previsto;
- righe 41-42: chiamata alla funzione g con parametri che non sono del tipo previsto;
Risultati
- Le righe 5–6 mostrano che la funzione f ha accettato entrambi i parametri float e li ha elaborati;
- Le righe 7–8 mostrano che la funzione `g` ha accettato entrambi i parametri di tipo `float` ma li ha convertiti in tipo `int` (riga 7);
Ora rimuoviamo il commento dalla riga 4:
Questa istruzione specifica che i tipi dei parametri formali devono essere rispettati. In caso contrario, viene segnalato un errore. I risultati dell'esecuzione diventano quindi:
- Righe 9–10: L'interprete PHP 7 ha generato un'eccezione per indicare che il primo parametro passato alla funzione `g` era di tipo errato. Si raccomanda di essere rigorosi riguardo ai tipi dei parametri, quando possibile, per rilevare gli errori nelle chiamate di funzione;
3.8.2. Risultati restituiti da una funzione
Lo script [base-15.php] è il seguente:
<?php
// types in strict mode
declare(strict_types=1);
// results rendered by a function
// a function can return several values in an array
list($res1, $res2, $res3) = f1(10);
print "[$res1,$res2,$res3]\n";
$res = f1(10);
for ($i = 0; $i < count($res); $i++) {
print "f1 : res[$i]=$res[$i]\n";
}
// a function can render an object
$res = f2(10);
print "f2 : [$res->res1,$res->res2,$res->res3]\n";
// what kind of object?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// we do the same with the f3 function
$res = f3(10);
print "f3 : [$res->res1,$res->res2,$res->res3]\n";
// what kind of object?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// end
exit;
// function f1
function f1(int $valeur): array {
// returns an array ($valeur+1,$valeur+2,$valeur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// function f2
function f2(int $valeur): object {
// renders an object ($valeur+1,$valeur+2,$valeur+3)
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// makes the object
return $res;
}
// function f3 - does the same thing as function f2
function f3(int $valeur): object {
// renders an object ($valeur+1,$valeur+2,$valeur+3)
$res = new stdclass();
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// makes the object
return $res;
}
Risultati
[11,12,13]
f1 : res[0]=11
f1 : res[1]=12
f1 : res[2]=13
Warning: Creating default object from empty value in C:\Data\st-2019\dev\php7\php5-exemples\exemples\bases\base-15.php on line 43
f2 : [11,12,13]
nature de l'objet : object(stdClass)#1 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
f3 : [11,12,13]
nature de l'objet : object(stdClass)#2 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
Commenti
- Il programma precedente mostra che una funzione PHP può restituire un insieme di risultati anziché uno solo, sotto forma di array o oggetto. Il concetto di oggetto è spiegato più dettagliatamente di seguito;
- righe 35–38: la funzione f1 restituisce più valori sotto forma di array;
- righe 41–48: la funzione f2 restituisce più valori sotto forma di oggetto;
- righe 51–59: la funzione f3 è identica alla funzione f2, tranne per il fatto che crea esplicitamente un oggetto alla riga 53;
- La riga 6 dei risultati mostra un avviso che indica che PHP è stato costretto a creare un oggetto predefinito alla riga 43 del codice, ovvero quando si utilizza la notazione [$res→res1]. La funzione var_dump alla riga 20 del codice rivela il tipo dell'oggetto e il suo contenuto. Nei risultati, vediamo che:
- riga 8: l'oggetto predefinito è di tipo stdClass;
- righe 9–10: la proprietà res1 è di tipo intero e ha il valore 11;
- ecc…
- Per evitare l'avviso alla riga 6 dei risultati, creiamo esplicitamente, alla riga 53 della funzione f3, un oggetto di tipo stdClass;
3.9. File di testo
Lo script [bases-16.php] è il seguente:
<?php
// strict adherence to function parameter types
declare (strict_types=1);
// sequential operation of a text file
// this is a set of lines of the form login:pwd:uid:gid:infos:dir:shell
// each line is put into a dictionary in the form login => uid:gid:infos:dir:shell
// set the file name
$INFOS = "infos.txt";
// we open it in creation
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// generate arbitrary content
for ($i = 0; $i < 100; $i++) {
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
}
// close the file
fclose($fic);
// we use it - fgets keeps the end-of-line marker
// this prevents the retrieval of an empty string when reading a blank line
// open it for reading
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
// lines are less than 1000 characters long
// line reading stops at the end-of-line mark
// or the end-of-file
while ($ligne = fgets($fic, 1000)) {
// delete the end-of-line marker if it exists
$ligne = cutNewLineChar($ligne);
// put the line in a table
$infos = explode(":", $ligne);
// retrieve login
$login = array_shift($infos);
// we neglect the pwd
array_shift($infos);
// create a dictionary entry
$dico[$login] = $infos;
}
// close it
fclose($fic);
// using the dictionary
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// end
exit;
// --------------------------------------------------------------------------
function afficheInfos(array $dico, string $clé): void {
// displays the value associated with key in the $dico dictionary if it exists
if (isset($dico[$clé])) {
// value exists - is it a painting?
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur is not an array
print "[$clé,$valeur]\n";
}
} else {
// $clé is not a key in the $dico dictionary
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// delete the end-of-line mark from $ligne if it exists
$L = strlen($ligne); // line length
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// end
return($ligne);
}
Il file infos.txt:
I risultati:
[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas
Commenti
- Riga 12: fopen(filename, "w") apre il file filename in scrittura (w=write). Se il file non esiste, viene creato. Se esiste, viene cancellato. Se la creazione fallisce, fopen restituisce false. Nell'istruzione if (!$fic = fopen($INFOS, "w")) {…}, ci sono due operazioni successive: 1) $fic=fopen(..) 2) if( ! $fic) {…} ;
- riga 18: fputs($fic,$string) scrive string nel file $fic. $string viene scritto con il carattere di nuova riga \n alla fine;
- riga 21: fclose($fic) chiude il file $fic;
- riga 26: fopen(filename,"r") apre il file filename in lettura (r=read). Se l'apertura fallisce (ad esempio, il file non esiste), fopen restituisce false;
- riga 34: fgets($fic,1000) legge la riga successiva del file, limitata a 1000 caratteri. Nel ciclo while ($line = fgets($fic, 1000)) {…}, ci sono due operazioni successive: 1) $line = fgets(…) 2) while ( ! $line). Dopo che l'ultimo carattere del file è stato letto, la funzione fgets restituisce false e il ciclo while si interrompe. Qui, la funzione fgets tenta di leggere fino a 1000 caratteri ma si interrompe non appena incontra un carattere di fine riga. Poiché tutte le righe qui hanno meno di 1000 caratteri, [fgets] legge una riga di testo, compreso il carattere di fine riga. La funzione cutNewLineChar nelle righe 75–84 rimuove eventuali caratteri di fine riga;
- riga 77: la funzione strlen($string) restituisce il numero di caratteri in $string;
- riga 78: la funzione substr($line, $position, $size) restituisce $size caratteri da $line, a partire dal carattere #$position, dove il primo carattere è #0. Su macchine Windows, il carattere di fine riga è "\r\n". Su macchine Unix, è la stringa "\n";
- riga 40: la funzione array_shift($array) rimuove il primo elemento da $array e lo restituisce come risultato. Qui, ignoriamo il risultato restituito da array_shift;
- Riga 62: la funzione is_array($variable) restituisce true se $variable è un array, false in caso contrario;
- riga 63: la funzione join fa la stessa cosa della funzione implode che abbiamo visto in precedenza;
3.10. Codifica/decodifica JSON

La codifica/decodifica JSON (JavaScript Object Notation) è qualcosa che useremo ampiamente nell'esercizio che costituisce il tema centrale di questo documento. Gli script [json-01.php, json-02.php, json-03.php] spiegano ciò che è necessario sapere per il resto del documento.
Lo script [json-01.php] è il seguente:
<?php
$array1 = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34];
// json encoding of array1 with escaped Unicode characters
print "encodage json du tableau array1 avec caractères Unicode échappés\n";
$json1 = json_encode($array1);
print "json1=$json1\n";
// json encoding of array1 with unescaped Unicode characters
print "encodage json du tableau array1 avec caractères Unicode non échappés\n";
$json2 = json_encode($array1, JSON_UNESCAPED_UNICODE);
print "json2=$json2\n";
// decoding jSON in associative array
print "décodage jSON de json2 dans tableau associatif\n";
$array2 = json_decode($json2, true);
var_dump($array2);
foreach ($array2 as $key => $value) {
print "$key:$value\n";
}
// decoding jSON in object
print "décodage jSON de json2 dans objet stdClass\n";
$array2 = json_decode($json2);
var_dump($array2);
print "prénom=$array2->prénom\n";
print "nom=$array2->nom\n";
print "âge=$array2->âge\n";
Risultati
Commenti
- Riga 6 del codice: la funzione [json_encode] converte il suo parametro in una stringa JSON;
- Riga 2 dei risultati: la stringa JSON generata. I caratteri Unicode éâ sono stati sostituiti dai loro codici Unicode, che iniziano con \u;
- riga 10 del codice: facciamo la stessa cosa, ma questa volta chiediamo che i caratteri Unicode vengano mantenuti così come sono;
- riga 4 dei risultati: la stringa JSON risultante. È molto più leggibile;
- Righe 14–18 del codice: eseguiamo l'operazione inversa. Convertiamo una stringa JSON in un array associativo;
- righe 6–13 dei risultati: vediamo che abbiamo recuperato un array associativo;
- righe 19–25 del codice: convertiamo una stringa JSON in un oggetto di tipo [stdClass];
- righe 18–25 dei risultati: vediamo che abbiamo recuperato un oggetto di tipo [stdClass];
- righe 23–25 del codice: l'attributo A di un oggetto O è indicato con [O→A];
È possibile codificare array a più livelli in JSON, come illustrato nel seguente script [json-02.php]:
<?php
$array = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34,
"mari" => ["nom" => "icariù", "prénom" => "ignacio", "âge" => 35],
"enfants" => [
["prénom" => "angèle", "age" => 8],
["prénom" => "andré", "age" => 2],
]];
// encoding jSON of the multi-level array
print "encodage jSON d'un tableau à plusieurs niveaux\n";
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
print "json=$json\n";
Risultati
encodage jSON d'un tableau à plusieurs niveaux
json={"nom":"séléné","prénom":"bénédicte","âge":34,"mari":{"nom":"icariù","prénom":"ignacio","âge":35},"enfants":[{"prénom":"angèle","age":8},{"prénom":"andré","age":2}]}
Commenti
Nella stringa JSON:
- gli array non associativi sono racchiusi tra parentesi quadre [] ;
- gli array associativi sono racchiusi tra parentesi graffe {};
Lo script [json-03.php] mostra come elaborare il seguente file JSON [family.json]:
{
"épouse": {
"nom": "séléné",
"prénom": "bénédicte",
"âge": 34
},
"mari": {
"nom": "icariù",
"prénom": "ignacio",
"âge": 35
},
"enfants": [
{
"prénom": "angèle",
"age": 8
},
{
"prénom": "andré",
"age": 2
}
]
}
Lo script [json-03.php] è il seguente:
<?php
// reading the jSON file
$json = file_get_contents("famille.json");
// json object decoding
$famille1 = json_decode($json);
print "----famille1\n";
var_dump($famille1);
// json decoding in associative array
print "----famille2\n";
$famille2 = json_decode($json, true);
var_dump($famille2);
Commenti
- riga 4: la funzione [file_get_contents] legge il contenuto del file denominato [family.json] e lo memorizza nella variabile [$json];
- La variabile viene quindi decodificata in un oggetto (righe 5–8) e in un array associativo (righe 9–12);
Risultati
----famille1
object(stdClass)#2 (3) {
["épouse"]=>
object(stdClass)#1 (3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
object(stdClass)#3 (3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
object(stdClass)#4 (2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
object(stdClass)#5 (2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
----famille2
array(3) {
["épouse"]=>
array(3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
array(3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
array(2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
array(2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
Commenti
- righe 1–38: l'oggetto risultante dalla decodifica del file JSON [family.json];
- righe 39-76: l'array associativo risultante dalla decodifica del file JSON [family.json];