[PILLOLE PHP] Gestire correttamente l’inclusione di files
In questa pillola tratteremo un argomento piuttosto semplice ma che se mal gestito può portare a dei grossi inconvenienti; l’argomento é l’inclusione di file.
Per quello che é la mia esperienza ho stabilito tre regole d’oro che dovrebbero bastare; se te ne vengono in mente altre sarò felice di discuterne.
1. Includere una sola volta
A meno che non sia strettamente necessario, é sempre meglio specificare che l’inclusione la vogliamo eseguire una sola volta utilizzando quindi i comandi include_once o require_once.
Facciamo un esempio per capire perché:
Il file 1.php contiene le definizioni di una serie di costanti.
I file 2.php e 3.php necessitano di alcune delle costanti definite in 1.php, dunque includeremo 1.php in entrambe i file.
Nella pagina page.php ci servono le funzioni contenute in 2.php e 3.php quindi li includeremo.
A questo punto se in 2.php e 3.php abbiamo incluso 1.php con il comando include, in page.php verrà sollevata una serie di errori di livello notice, in quanto tentiamo di definire due volte le stesse costanti contenute in 1.php.
Utilizzando include_once risolviamo questi problemi. Utilizziamo dunque include e require solo quando é necessario ripetere più volte l’inclusione.
2. Percorsi assoluti
Se vogliamo includere dei file in un file che a sua volta sarà incluso, é importante farlo attraverso dei percorsi assoluti. Si prenda ad esempio la seguente struttura:
Ora, il file db_config.php conterrà i parametri di connessione al database e dovrà essere incluso nel file db_connect.php che a sua volta provvederà alla connessione.
Sarebbe tuttavia un errore includerlo in questo modo:
include_once ‘db_config.php’;
Il file db_connect.php sarà infatti utilizzato in index.php, dunque dovremmo includere db_config.php in db_connect.php in questo modo:
include_once ‘inc/db_config.php’;
Ma cosa succede se il file db_connect.php dovrà essere utilizzato anche da admin.php?
Un pasticcio.
Se vogliamo includere dei file in file che a loro volta verranno inclusi, lo dobbiamo fare tramite percorsi assoluti. Dunque includeremo db_config.php in db_connect.php in questo modo:
include_once dirname(__FILE__) . ‘/db_config.php’;
La costante magica __FILE__ restituisce il percorso assoluto dove risiede fisicamente il file (diverso da $_SERVER[‘PHP_SELF’] che restituisce il percorso dove il file viene eseguito). Quindi con dirname() preleviamo unicamente il percorso.
A questo punto non abbiamo che da aggiungere il percorso del file che intendiamo includere; in questo caso si trova nella stessa cartelle quindi é molto semplice.
In questo modo, in qualunque punto andremo ad includere db_connect.php, il file db_config.php verrà incluso correttamente in quanto prelevato dalla sua posizione assoluta.
Nota: A partire da PHP 5.3 é stata introdotta la cosatante magica __DIR__ che equivale a
dirname(__FILE__)
3. Prestare attenzione alle inclusioni dinamiche
Molta attenzione direi. Questo codice:
include $_GET[‘page’];
senza nessun accorgimento equivale, dal punto di vista della sicurezza, ad un suicidio.
Per evitare ogni problema, ti rimando alla completissima guida sulla sicurezza scritta da Cristian, in particolare questo articolo, al capitolo indirezione.
Conlusione
Come vedi, anche per un semplicissimo argomento quale l’inclusione di file, c’é comunque parecchio da dire.
18 commenti
Trackback e pingback
-
Tweets that mention [PILLOLE PHP] Gestire correttamente l’inclusione di files | Your Inspiration Web -- Topsy.com
[...] This post was mentioned on Twitter by Antonino Scarfì, Simone D'Amico. Simone D'Amico said: [PILLOLE PHP] Gestire correttamente l’inclusione…
Bravo Maurizio ;)
Grazie Rocco :-)
Ciao Maurizio,
solo una puntualizzazione sulle prestazioni: include_once è leggermente più lenta di include in quanto ovviamente deve controllare se il file è già stato incluso o meno.
Io comunque ho definitivamente risolto il problema passando alla programmazione ad oggetti e creando un semplice autoloader ;)
Credo (non sono sicuro, ma appena ho tempo vado a vedere i sorgenti) che non faccia un controllo tipo if/else. Se ben ricordo aggiungendo once viene maracto il percorso; questo non incide sulle prestazioni, semplicemente il percorso viene ignorato. ma ti farò sapere
In questo blog c’è un test sull’argomento:
http://arin.me/blog/php-require-vs-include-vs-require_once-vs-include_once-performance-test
include sembra quindi risultare più veloce di include_once.
Comunque sono tempi piuttosto relativi…
Interessante soprattutto l’aspetto del la funzione dirname(), unica cosa non ho ben capito come sfruttare al massimo questa funzione. Ad esempio, mettiamo che ho per assurdo due file con lo stesso nome in due locazioni diverse, e scrivo dirname(__FILE__).”/nomefile.php” cosa succede? quale preleva PHP in automatico dei due percorsi? Mi restituisce un errore? Infine volevo sapere se esiste una funzione come questa ma per le directory, se voglio puntare una directory sul mio server ma non me ne ricordo (per assurdo) la posizione, c’è un modo per farla puntare in automatico da php?
Grazie ;-)
succede che viene incluso nomefile.php contenuto nella cartella nella quale risciede il file che lo invoca.
Credo che non hai capito bene lo scopo di questa procedura.
Guarda la struttura delle cartella che ho inserito nell’articolo.
Se includo db_config.php in db_connect.php che percorso dovrò dare all’inclusione?
dipende:
se utilizzo db_connect.php nella cartella inc
include ‘db_config.php’;
se lo utilizzo nella root
include ‘inc/db_config.php’;
se lo utilizzo in admin
include ‘../inc/db_config.php’;
Ovviamente é un problema
Invece se nel file db_connect.php includerò db_config.php in questo modo
include dirname(__FILE__) . ‘/db_config.php’;
in qualunque punto includerò questo script il percorso che risulterà sarà sempre tipo
/var/www/inc/db_config.php
Ciao Maurizio, ormai sono un tuo lettore assiduo :-)
Io per non sbagliare utilizzo sempre insieme all’include $_SERVER[‘DOCUMENT_ROOT’] + il path. Mai avuto un problema….
ciao Cardy.
Certo, la tua é un’altra possibilità.
Articolo sintetico, chiaro, diretto e utile. Grazie!
Grazie Mesillo
Ciao Maurizio,
purtroppo mi faccio risentire solo ora perche ho avuto dei problemi e non ho potuto piu risponderti, eravamo rimasti al fatto che mi davi questa dritta:
——
Invece se nel file db_connect.php includerò db_config.php in questo modo
include dirname(__FILE__) . ‘/db_config.php’;
in qualunque punto includerò questo script il percorso che risulterà sarà sempre tipo
/var/www/inc/db_config.php
——
ma anche in questo modo, non si pone ugualmente il problema? infatti anche se il file db_config.php sarà puntato in modo assoluto in tutto il sito, il problema mi si sposterà sul file db_connect.php che in base a dove mi troverò il percorso dovrà variare… diciamo che in questo modo, se ho capito bene, risolvo il problema per il file db_config.php, ma lo sposto sul file db_connect.php
Dov’è che sbaglio il mio ragionamento?
Il problema si pone solo sui file inclusi in file che andranno a loro volta inclusi.
db_connect viene incluso direttamente quindi non si pone nessun problema
ahhhhhh ok :D
adesso è tutto chiaro. grazie
Io non ho ben capito una cosa.
Ti mostro il mio esempio pratico.
Nella root del sito ho una cartella che si chiama classes. Al suo interno c’è il file class.php.
Ora, il file class.php deve essere incluso in index.php che si trova nella root del sito.
Quindi per includere correttamente il file dovrò fare include_once __DIR__ . ‘/classes/class.php’; giusto?
Se io ho due file (principale.php e da_includere.php) come posso verificare se il file è stato incluso?
Semplice usando la funzione:
require(“paginadaincludere.php”);
Se non restituisce errore il file è stato incluso correttamente.