mercoledì 11 giugno 2008

PHP - "require" e "include"... questi "conosciuti"

Le istruzioni "require" e "include" (insieme alla varianti "require_once" e "include_once") sono utilizzatissime in PHP.
Appunto per questo talvolta non si presta attenzione alla pagina del manuale.

Esse inserisco uno script nello script corrente. Ma attenzione ai path name!
Se il file da includere è nella stessa directory di dove si trova lo script che include, oppure il file da includere è nel "include_path" del php.ini, basta scrivere il nome del file da includere.

Ma se si trova in un'altra directory e volete usare un path name relativo, dovete sempre tener ben presente che la directory corrente (.) è la directory di dove si trova il file servito dal server web.


E fin qui niente di strano! Qualche problema se non si sta attenti potrebbe verificarsi quando si includono a cascata più file (magari contenenti delle classi).
Faccio un esempio abbastanza banale.

avendo una struttura di directory con i seguenti file (pattern MVC):
- app/classes/user.class.php, una classe che gestisce lettura/scrittura sul db dei dati di un utente
- app/controllers/user_controller.class.php, classe che gestisce la visualizzazione
- app/templates/user.edit.php, template per la modifica di un utente
- app/templates/user.view.php, template per la visualizzazione di un utente
- public_htm/index.php, pagina servita dal server web (istanzia il controller)

In una configurazione simile a questa potremmo pensare che le righe iniziali dei file siano le seguenti:
user.class.php
<?php
class user {
...
}
?>

user_controller.class.php

<?php require_once ("../app/classes/user.class.php");
class user_controller {
...
function edit(){
... // Do some work
include_once ("../app/view/user.edit.php");
}
function view(){
... // Do some work
include_once ("../app/templates/user.view.php
}
?>

index.php

<?php
require_once ("../app/controllers/user_controller.class.php");
$controller = new user_controller();
?>


Ovviamente tralasciando i file della directory app/templates/ perchè conterranno principalmente codice
HTML.


Il problema si porrebbe a questo punto se si vuole aggiungere una directory "public_html/admin/"
dove porre un'area riservata per un amministratore del nostro sito web.
Nel nostro ipotetico file "public_html/admin/edit_user.php", se vogliamo utilizzare sempre le stesse classi
per gestire la scrittura e la lettura da db (il che non sarebbe male, in quanto avremmo scritto del codice
una sola volta!) tutti i path name inseriti fino adesso...vanno a farsi benedire.


La soluzione è dietro l'angolo: basterebbe inserire path name assoluti e non relativi.
Ovviamente cambiando server (banalmente passando da sviluppo a produzione) dovremmo cambiare
tutti i path name. E qui però ci vengono in aiuto le define.

Creiamoci una directory config/ (allo stesso livello di app/ e public_html/).
All'interno, un file path.php che contiene una o più define, per esempio:


<?php
define ('APP_BASE_DIR',"/home/www/app/");
?>

e sostituiamo tutti i path negli include e i require con qualcosa tipo:

require_once (APP_BASE_DIR."classes/user.class.php");

Nei file "index.php" e "edit_user.php", utilizzeremo il path relativo per includere il file "config/paths.php" (nel primo anteponendo "../" e nel secondo "../../),mentre per tutti gli altri file l'inclusione verrà effettuata senza problemi utilizzando il path name assoluto.

Se non sapete quale sia il path name assoluto del vostro server ricordatevi del comando "getCwd()".
Piazzandoci un bel "echo" davanti in uno script, verrete a conoscenza del path name assoluto utilizzato sul vostro server.
Ovviamente ricordatevi di eliminare al più presto tale script, prima che possa essere fonte di vulnerabilità.

Nessun commento: