La gestione dei file di testo in PHP

Lezione in IV E Sistemi informativi aziendali 
date delle lezioni: 12, 19 e 26 settembre 2016
data delle lezioni: 18 e 25 settembre 2017

Gli archivi testuali sono dei semplici documenti di testo (.txt) in cui vengono salvati dei dati per poi essere letti tramite script php.

In particolare php offre una gamma di funzioni atte alla scrittura e lettura dei file in cui potranno essere salvati dei dati e letti all'occorrenza.


LIMITI DEI FILE DI TESTO

Occorre fin da subito chiarire un punto: i FILE DI TESTO sono utilizzabili solo nel caso in cui la mole di dati in esso contenuta è relativamente piccola e soggetti a sporadiche modifiche.

Infatti avranno una gestibilità decisamente molto più complessa e limitata rispetto a quella ottenibile con un database MySql dato che non sarà possibile formulare le query.
Inoltre, risulta quasi del tutto impossibile istaurare relazioni fra i dati.


IL FUNZIONAMENTO

Al fine di gestire i dati contenuti in un file .txt occorrerà:
  • "scrivere" il file con una idonea formattazione;
  • eseguire operazioni su di esso ricorrendo ad alcune funzioni; fra le tante, ve ne sono alcune che assumono particolare rilievo: fopen(), fread(), fwrite(), fclose(), file() ed explode().

Chiariamo i due concetti esaminandoli separatamente.



LA FORMATTAZIONE DI UN FILE DI TESTO

Un file .txt si articola in più righe: ognuno di esse potrà rappresentare un set di dati.

Ad esempio poniamo di voler costruire un archivio in cui salvare i dati riguardanti dei prodotti su un file di testo: ogni riga potrà rappresentare un prodotto.
Tuttavia, per ogni prodotto inserito occorrerà salvare più di una informazione: poniamo, ad esempio, di voler salvare il nome, la taglia e il prezzo.
Affinche più dati siano scritti su un'unica riga occorrerà strutturare una formattazione adeguata. Vediamone un esempio:

capo|taglia|prezzo

Pertanto il file di testo che possiamo chiamare prodotti.txt avrà una struttura di questo genere:
  1. camicia|S|150  
  2. felpa|XXL|220  
  3. t-shirt|M|250  

In pratica i tre dati (nome, taglia e prezzo) che desideriamo salvare su un'unica riga del file .txt saranno separati gli uni dagli altri da un carattere separatore (poco comune) a nostra scelta, nell'esempio "|".

Quindi, un archivio testuale è un file .txt in cui ciascuna riga contiene uno o più dati e all'interno della riga e i singoli dati sono separati da una carattere separatore.
Ciò sarà rilevante sia in fase di lettura, sia in fase di scrittura del file.


LA LETTURA

In fase di "lettura" è possibile far ricorso a diverse funzioni che tuttavia presentano ognuna delle specifiche particolarità.
Quella che in caso di database testuali risulta essere maggiormente utile è file().

La funzione file() accetta come unico parametro il percorso al file che si desidera leggere ed esegue una lettura del file riga per riga restituendo un array in cui ciascun elemento è costituito da un rigo.
Ovviamente, avendo ottenuto un array, questo potrà essere letto con un classico ciclo foreach.

Scorrendo il nostro array otterremo una singola riga per ogni ciclo; per isolare i singoli dati presenti all'interno di tale riga si farà ricorso alla funzione explode().

La funzione explode() riceve due parametri obbligatori: il primo è il carattere separatore; il secondo è una stringa da trasformare in un array.

Vediamo cosa avremo:
  1. <?php  
  2. $my_database_txt = 'prodotti.txt';  
  3. $array_righi = file($my_database_txt);  
  4. foreach($array_righi as $key => $capi){  
  5.     list($capo$taglia$prezzo) = explode("|"$capi);  
  6.     echo '  
  7.         <p>  
  8.         Capo: ' .$capo. '<br />  
  9.         Taglia: ' .$taglia. '<br />  
  10.         Prezzo: ' .$prezzo. '<br />  
  11.         <a href="action.php?delete=' .$key. '">Elimina</a> - <a href="form_update.php?row=' .$key. '">Modifica</a>  
  12.         </p>  
  13.         <hr />';  
  14.     }  
  15. ?>  

Si ponga attenzione ai link per eseguire l'eliminazione e la modifica di un prodotto il cui funzionamento sarà di seguito illustrato.


LA SCRITTURA

Per poter scrivere su un file di testo occorre anzitutto assicurarsi che questo abbia i permessi di scrittura: a questo scopo può essere utile la funzione is_writable(). Essa prende come parametro il percorso al file e restituisce un valore boleano, TRUE se il file può essere scritto.

La scrittura del file avverrà con le funzioni fopen()fwrite() e fclose().

La funzione fopen() serve per apire il collegamento con la risorsa (il file da scrivere). Essa prevede due parametri obbligatori: il percorso al file e una stringa che ci indicherà modalità con la quale si vorrà operare sul file (si rimanda al manuale per maggiori dettagli).
La funzione fwrite() esegue la scrittura sul file e prevede due parametri: la risorsa e la stringa da scrivere.
Infine, la funzione fclose() esegue la chiusura del file e prevede come unico parametro la risorsa.

Avremo una pagina con un banale form:
  1. <form action="action.php" method="post">  
  2. <label for="capo">Capo</label>  
  3.     <input type="text" id="capo" name="capo" />  
  4. <label for="taglia">Taglia</label>  
  5.     <input type="text" id="taglia" name="taglia" />  
  6. <label for="prezzo">Prezzo</label>  
  7.     <input type="text" id="prezzo" name="prezzo" />  
  8.       
  9.     <input type="submit" name="scrivi" value="scrivi" />  
  10. </form>  

E poi avremo una pagina (action.php) che eseguirà la scrittura sul un file prodotti.txt:
  1. <?php  
  2. $my_database_txt = 'prodotti.txt';  
  3. if(isset($_POST['scrivi']))  
  4.     {  
  5.     if(!is_writable($my_database_txt)){  
  6.         exit("il file non ha i permessi di scrittura!");  
  7.         }  
  8.     // riceviamo i dati e li filtriamo  
  9.     $bad_char = array("|""rn""r""n");  
  10.     $capo = str_replace($bad_char""$_POST['capo']);  
  11.     $taglia = str_replace($bad_char""$_POST['taglia']);  
  12.     $prezzo = str_replace($bad_char""$_POST['prezzo']);  
  13.     // apriamo il file  
  14.     $open = fopen($my_database_txt"a+");  
  15.     // scriviamo i dati separati dal carattere separatore  
  16.     fwrite($open$capo."|".$taglia."|".$prezzo."rn");   
  17.     // chiudiamo il file     
  18.     fclose($open);  
  19.       
  20.     // ritorniamo nella pagina di visualizzazione  
  21.     header("location: lettura.php");  
  22.     exit;  
  23.     }  
  24. ?>  

ELIMINARE UNA RIGA DAL FILE .TXT

Eliminare un rigo sta a significare, nel caso del nostro archivio basato su file di testo, eliminare un prodotto. Abbiamo precedentemente visto che ciascun prodotto avrà un link per l'eliminazione scritto attaverso un ciclo foreach di questo tipo (si veda il codice per eseguire la lettura):

  1. <a href="action.php?delete=' .$key. '">Elimina</a>  

La variabile $key all'interno del ciclo individua la chiave dell'array ottenuto con la funzione file() e, quindi, ci consente di individuare il rigo specifico che vogliamo eliminare. Nel file action.php pertanto avremo:

  1. if(isset($_GET['delete']))  
  2.     {  
  3.     // creiamo l'array con tutti i righi  
  4.     $array_righi = file($my_database_txt);  
  5.     // eliminiamo dall'array il rigo la chiave inviata via get  
  6.     unset($array_righi[$_GET['delete']]);  
  7.     // apriamo il file resettando il contenuto  
  8.     $open = fopen($my_database_txt"w");  
  9.     foreach($array_righi as $key => $value){  
  10.         // ri-scriviamo tutti i righi (rimanenti)  
  11.         fwrite($open$value);  
  12.         }  
  13.     fclose($open);  
  14.     // ritorniamo nella pagina di visualizzazione  
  15.     header("location: lettura.php");  
  16.     exit;  
  17.     }  

Occorre notare che conla funzione unset() eliminiamo l'elemento dall'array; inoltre la funzione fopen, a differenza di quando fatto in precedenza, avrà come secondo parametro w e quindi questo verrà cancellato di tutto il suo contenuto e riscritto di nuovo ma senza il rigo eliminato.
Il codice proposto necessiterebbe di ulteriori e più rigidi controlli (quantomento con array_key_exists) ma ho voluto ridurre al minimo lo script.


LA MODIFICA DI UNA RIGA DI UN FILE .TXT

La modifica della singola riga segue una logica per molti aspetti simile a quella vista per l'eliminazione. Tuttavia in questo caso avremo uno step ulteriore: dovremo precompilare un form con i dati correnti della riga che desideriamo modificare e poi, al submit di tale form, eseguire la modifica.

Anzitutto esaminiamo il link che rimanda alla pagina di modifica che, ricordo, viene prodotto all'interno del ciclo foreach (si veda il codice per eseguire la lettura):
  1. <a href="form_update.php?row=' .$key. '">Modifica</a>  


Come detto in precedenza per l'eliminazione, $key ci permetterà di individuare la riga che desideriamo modificare. In questo caso dovremo estrarre i dati contenuti in tale riga e compilare i value del form:
  1. <?php  
  2. $my_database_txt = 'prodotti.txt';  
  3. if(!isset($_GET['row'])){  
  4.     header("location: lettura.php");  
  5.     exit;  
  6.     }  
  7. $array_righi = file($my_database_txt);  
  8. if(!isset($array_righi[$_GET['row']])){  
  9.     exit('errore nella chiave');  
  10.     }  
  11. list($capo$taglia$prezzo) = explode("|"$array_righi[$_GET['row']]);  
  12. ?>  
  13. <html>  
  14. <head>  
  15. </head>  
  16. <body>  
  17. <h2><a href="lettura.php">Torna alla lista degli articoli</a></h2>  
  18. <form action="action.php" method="post">  
  19. <label for="capo">Capo</label>  
  20.     <input type="text" id="capo" name="capo" value="<?php echo htmlentities($capo, ENT_QUOTES); ?>" />  
  21. <label for="taglia">Taglia</label>  
  22.     <input type="text" id="taglia" name="taglia" value="<?php echo htmlentities($taglia, ENT_QUOTES); ?>" />  
  23. <label for="prezzo">Prezzo</label>  
  24.     <input type="text" id="prezzo" name="prezzo" value="<?php echo htmlentities($prezzo, ENT_QUOTES); ?>" />  
  25.     <input type="hidden" name="row_update" value="<?php echo $_GET['row']; ?>" />  
  26.     <input type="submit" name="modifica" value="modifica" />  
  27. </form>  
  28. </body>  
  29. </html>  

Si noti il campo name="row_update" di tipo hidden che avrà come value la chiave inviata via get. All'invio del form andremo a recuperare i dati inviati: i nuovi valori che dovrà assumere la riga e la riga da modificare (presente nel campo hidden). Pertanto avremo:

  1. $my_database_txt = 'prodotti.txt';  
  2. if(isset($_POST['modifica']) AND isset($_POST['row_update']))  
  3.     {  
  4.     // creiamo l'array con tutti i righi  
  5.     $array_righi = file($my_database_txt);  
  6.     // riceviamo i dati e li filtriamo  
  7.     $bad_char = array("|""rn""r""n");  
  8.     $capo = str_replace($bad_char""$_POST['capo']);  
  9.     $taglia = str_replace($bad_char""$_POST['taglia']);  
  10.     $prezzo = str_replace($bad_char""$_POST['prezzo']);  
  11.     // ri-scriviamo il rigo (che sostituirà il precedente)  
  12.     $array_righi[$_POST['row_update']] = $capo."|".$taglia."|".$prezzo."rn";  
  13.     // apriamo il file resettando il contenuto  
  14.     $open = fopen($my_database_txt"w");  
  15.     foreach($array_righi as $key => $value){  
  16.         // ri-scriviamo tutti i righi  
  17.         fwrite($open$value);  
  18.         }  
  19.     fclose($open);  
  20.     // ritorniamo nella pagina di visualizzazione  
  21.     header("location: lettura.php");  
  22.     exit;     
  23.     }  

Come possiamo notare lo script segue una logica analoga a quella vista per l'eliminazione con l'unica differenza che anzichè eliminare l'elemento dall'array $array_righi con unset lo andremo a valorizzare con i nuovi valori (opportunamente filtrati) provenienti dal form, semparando i valori con il carattere semparatore | e aggiungendo a fine stringa il ritorno a capo.

Di seguito il link al download dei file in cui è presente lo script completo.

fonte:http://www.miniscript.it/articoli/57/la_gestione_di_database_testuali_txt.html

Commenti