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

Le nuove variabili superglobali

Le novità principali a partire dalla versione 4.1.0 di Php
Le novità principali a partire dalla versione 4.1.0 di Php
Link copiato negli appunti

Introduzione

Il 10 Dicembre 2001 il "Php team" ho rilasciato, dopo un grosso lavoro di test, la versione 4.1.0 del famoso linguaggio di scripting. Questa versione più di altre ha introdotto una grossa novità: nuove variabili per i dati provenienti dal "mondo esterno".

Purtroppo molti hoster non hanno aggiornato i server, lasciando quindi agli sviluppatori una scelta: supportare o meno il vecchio stile di programmazione.

Chiariamo meglio questo punto. In Php, a differenza di altri linguaggi di scripting, le variabili esterne, provenienti cioè da una richiesta get, post, dai cookie, salvate in sessioni, venivano create autonomamente dall'interprete. Ad esempio, se richiamavo lo script var.php passando una variabile via get (in questo modo: var.php?a=3), nello script era resa disponibile una variabile $a.

A questo punto si poneva però un problema: e se una stessa variabile fosse stata inviata allo stesso tempo via get e via post? A questo proposito nel php.ini era disponibile la direttiva variables_order che permetteva di specificare l'ordine in cui dovevano essere recuperate le variabili esterne.

Rimaneva ancora un problema di sicurezza in quanto un programmatore avrebbe potuto fare un controllo su una variabile $var che veniva considerata sicura perché salvata in una sessione o restituita da una funzione, mentre invece la variabile controllata veniva passata maliziosamente da un utente via get.

Alcuni famosi script che non utilizzavano gli array ($HTTP_*_VARS) per operare con le variabili esterne hanno avuto dei bug dovuti a ciò.

Le novità

Con la versione 4.1.0 vengono introdotte i nuovi array per i dati esterni:

  • $_GET al posto di $HTTP_GET_VARS
  • $_POST al posto di $HTTP_POST_VARS
  • $_SERVER al posto di $HTTP_SERVER_VARS
  • $_COOKIE al posto di $HTTP_COOKIE_VARS
  • $_ENV al posto di $HTTP_ENV_VARS
  • $_SESSION al posto di $HTTP_SESSION_VARS

e un array che non possiede corrispondenti con le precedenti versioni:

  • $_REQUEST che unisce i contenuti di $_GET, $_POST e $_COOKIE

Queste variabili presentano una grossa novità rispetto alle precedenti: sono superglobali.
In sostanza è possibile accedere a queste variabili dalle funzioni senza la necessità di dichiararle global. Hanno cioè un ambito (scope) globale.

Con la versione 4.2.0 viene invece introdotta un'altra novità importante: la direttiva "register_globals" viene impostata di default su "off" per cui non vengono più create variabili con i nomi passati dall'esterno (l'esempio della variabile $a), ma vengono semplicemente creati degli indici negli array superglobali.

Purtroppo la maggior parte degli script erano sviluppati per utilizzare il "register_globals = On" anche se il Php team da molto tempo indicava chiaramente di utilizzare gli array $HTTP_*_VARS.

Un po' per il funzionamento degli script, un po' per la diffidenza verso le nuove versioni, molti hoster hanno deciso di non passare alle nuove versioni di Php (nonostante quelle vecchie presentassero anche dei bug), e molti non hanno fatto il passaggio neppure ora a distanza di oltre un anno.

A questo punto si pongono dunque due problemi opposti da risolvere: far funzionare vecchi script su versioni di Php nuove e rendere i nuovi script almeno in parte retrocompatibili.

La retrocompatibilità

Prima di iniziare questo paragrafo una premessa: non è in genere possibile rendere retrocompatibili script di terzi scritti per le nuove versioni di Php senza un grande lavoro di riscrittura del codice e comunque il gioco non vale la candela. Per cui questo paragrafo è indicato a chi vuole progettare uno script che funzioni anche con le versioni precedenti alla 4.1.0.

Come abbiamo visto la differenza principale tra le versioni vecchie e le nuove è rappresentato dagli array contenenti i dati esterni e dal fatto che siano superglobali.

Per farlo dobbiamo assegnare alle variabili di tipo $_* non presenti nelle versioni antecedenti alla 4.1.0 i valori delle variabili $HTTP_*_VARS.

Quindi per prima cosa dovremo controllare la versione del Php con cui sta girando lo script. Ci sono vari modi per farlo:

  • - controllare l'esistenza di una funzione aggiunta con la versione 4.1.0
  • - usare la funzione phpversion()
  • - controllare che non siano presenti gli array $_*

Vediamo come utilizzare ognuno di questi tre punti:

<?php // controllo l'esistenza di una funzione aggiunta con Php 4.1.0
if( !function_exists('version_compare') ){
echo "php < 4.1.0";
}
else{
echo "php >= 4.1.0";
}
?>

<?php // controllo attraverso phpversion
$version = intval(str_replace('.', '', phpversion()));
if( $version < 410 ){
echo "php < 4.1.0";
}
else{
echo "php >= 4.1.0";
}
?>

<?php // controllo attraverso gli array delle variabili esterne
if( !isset($_SERVER)
OR !$_SERVER
OR !is_array($_SERVER)
OR count(array_diff($_SERVER, $HTTP_SERVER_VARS)) ){
echo "php < 4.1.0";
}
else{
echo "php >= 4.1.0";
}
?>

Le tre soluzioni sono equivalenti, magari la prima è più elegante, ma sta al programmatore scegliere quella che più gli è congeniale.

Una volta determinata la versione di Php del server, dobbiamo soltanto aggiungere i riferimenti ai nuovi array:

<?php //esempio usando function_exists
if( !function_exists('version_compare') ){
$_GET = &$HTTP_GET_VARS;
$_POST = &$HTTP_POST_VARS;
$_SERVER = &$HTTP_SERVER_VARS;
$_COOKIE = &$HTTP_COOKIE_VARS;
$_ENV = &$HTTP_ENV_VARS;
$_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}
?>

La retrocompatibilità delle sessioni è un argomento un po' più complesso e verrà trattato in un articolo sulle sessioni e la retrocompatibilita.

Vecchi script su nuove versioni di Php

Per garantire il funzionamento di script progettati per le vecchie versioni con una nuova versione di Php, esistono varie soluzioni:

  • - cambiare il valore di register_globals nel Php.ini
  • - cambiare il valore di register_globals attraverso il file di configurazione di apache
  • - usare la funzione extract per simulare il register_globals

La prima soluzione non è molto raffinata e può portare a problemi di sicurezza sul server, in quanto tutti gli script Php dell'intero server avranno il registr_globals variato.

La seconda soluzione è meno invasiva e più raffinata: attraverso i file di configurazione di apache è possibile attivare una direttiva del php.ini per un solo dominio o per una sola directory o per un solo file, rendendo il tutto trasparente agli altri ospiti del server. Farlo è molto semplice, basta infatti aggiungere nel file httpd.conf questa riga:

php_admin_value "register_globals" "On"

nelle proprietà del dominio, directory o file interessati.

Mentre queste due soluzioni richiedono l'intervento dell'amministratore del server, è possibile fare in piccolo qualcosa del genere utilizzando la funzione extract().

Questa funzione estrae i valori dagli array creando variabili con lo stesso nome, esattamente come sarebbe successo se la direttiva register_globals fosse stata attiva.

Basta aggiungere una riga del genere in testa allo script, considerando che l'ordine degli array passati alla funzione array_merge varia la precedenza degli stessi: se due array hanno uno stesso indice, il valore presente nel secondo array sovrascrive quello del primo.

extract(array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV));

Ti consigliamo anche