ansorweb, l'ultima spiaggia

Sei in: Home >>Guide

Siti in php con database piccoli e piu' file di testo


di Antonella Sorbini  16 luglio 2019

Provare a vivere con meno database e più file testo è possibile, nel senso che non è affatto detto che i contenuti di un testo, di un titolo e tutto quello che viene normalmente scritto, debba essere per forza contenuto in un campo di tabella, molto spesso è più utile lavorare con le inclusioni di file di testo, soprattutto per non avere problemi con il riconoscimento dei caratteri speciali, accentati e in lingue di tutti i tipi. Inoltre personalmente preferisco che i database siano ridotti al minimo, visto che magari uno paga al gestore del dominio il database un tanto al Gigabyte, mentre non si ha limite nello spazio da usare per i documenti, e il progetto che si ha in mente è una mole di dati sconfinata. Conviene pertanto pensare a organizzarsi anche in altri modi, senza peraltro andarsi a complicare troppo la vita.

Proviamo quindi a ragionare pensando su quale sia la potenza di un database: la gestione delle relazioni. Benissimo, quelle gli si lasciano tutte, anzi magari un database più snello ce lo possiamo gestire con più facilità logica. Come me la organizzo la tipica tabella di base che contiene il grosso delle informazioni che trovo in una pagina dinamica?

Se mi abituo a pensare solo in termini di database, aldilà delle relazioni tra varie tabelle possibili, costruisco una cosa del genere:

idArticolo titoloArticolo testoArticolo altro
contatore testo testo ...
.... .... .... ...

quello che poi farò nel codice della pagina php è costruire una query Select che mi richiama quei contenuti, li organizzo ad esempio in un array e li memorizzo in tante variabili quanti sono i campi del database. Ogni variabile contiene l'elemento della pagina che mi interessa , quindi andrò a stampare i testi con un codice tipo

<?php

//codice vario...

echo $titoloArticolo;

echo $testoArticolo;

//codice vario...

?>

 

E se invece voglio usare le inclusioni di file di testo che mi sono scritto e messo da parte in una cartella opportuna?

il primo passaggio logico che ho fatto personalmente è stato quello di inserire non il testo vero e proprio nel database ma il nome del file da includere e costruirmi le cartelle con i file relativi per tenerli in ordine. I nomi dei file li inserisco come 'autoesplicativi', nel senso che li nomino con lo stesso testo del titolo togliendo gli spazi e facilitandomi la loro ricerca al volo nelle cartelle che li contengono. Questo sito per esempio è costruito attualmente in questo modo anche se è in ASP, ma la logica è la stessa.

Quindi la tabella diventa:

idArticolo titoloArticolo testoArticolo altro
contatore1 titoloPincoPallino.txt testoPincoPallino.txt ...
contatore2 titoloSempronio.txt testoSempronio.txt ...

E il codice come diventa? Eccolo, ridotto ai minimi termini saltando la parte della query e la memorizzazone delle variabili:

<?php

//codice vario

include'cartellaTitoli/'.$titoloArticolo ;

include 'cartellaTesti/'.$testoArticolo;

//codice vario

?>

Ok, ora però ragioniamoci ancora sopra: in questo modo devo comunque mettere un nome di file nel database, e questo nome, se lo prendo dal titolo dell'articolo può pure essere di lunghezza molto variabile. Se voglio compattare il più possibile il db e automatizzare il più possibile le operazioni di immissione dati, i nomi dei dei file me li posso costruire a tavolino sfruttando proprio il numero del contatore che mi identifica il record e dandogli un nome corto corto, ottenendo una cosa del tipo:

idArticolo titoloArticolo testoArticolo altro
contatore1 titolo1.txt testo1.php ...
contatore2 titolo2.txt testo2.php ...
... ... ... ..

E come si fa? Per farlo sfrutto il codice SQL del database all'atto dell'immissione dei dati dandogli come direttiva in aggiornamento il fatto di riempire il campo mettendo una determinata stringa precostituita ('testo' oppure 'titolo' appunto)+ il valore del contatore corrente.

Non esplicito il codice relativo perchè in realtà voglio arrivare direttamente al punto successivo proseguendo il ragionamento:

Se il nome dei file è sempre lo stesso con l'unica variante del numero del contatore corrente, allora posso pure lavorare direttamente col codice php per ricavare il nome del file, visto che tanto lo decido io con l'utilizzo del contatore, e costruire il percorso dell'inclusione in modo opportuno:

<?php

//codice vario

include'cartellaTitoli/titoloArticolo'.$idArticolo.'txt' ;

include 'cartellaTesti/testoArticolo'.$idArticolo.'php';

//codice vario

?>

Bene quindi ho appena preso i dati che mi servono dal database per recuperare i file usando solo il campo contatore, e gli altri campi allora , dove si trovavano i nomi dei file? Niente, non servono più, si possono buttare al secchio, e il database diventa così

idArticolo altro
contatore1 ...
contatore2 ...
... ..

il DB più piccolo e compatto che esista. Ovviamente ci saranno altri campi con le date, relazioni varie, però i file di testo è giusto che siano file di testo veri e propri che si trovano nelle loro rispettive cartelle di appartenenza e che mi sono costruito a parte.

Quindi in ultima analisi è possibile vivere con meno database e più file di testo senza che questo generi confusione e mantenendo comunque le relazioni tra le tabelle.

Tutto fila liscio se uno imposta i dati in partenza in questo modo: si fa un piccolo database, i file si memorizzano a parte con i nomi ricavati dai contatori dei record corrispondenti e si va avanti così, già, ma se uno si ritrova a migrare da un sistema all'altro? si parte da un database con dentro di tutto e bisogna fare in modo di estrarre quei dati e portarli nei file esterni che poi andremo a includere nel codice della pagina dimanica.

Se ci si trova a maneggiare database con un migliaio di record è impensabile mettersi a fare una cosa del genere a mano, siamo matti? ci si rinuncia in partenza. Ovviamente sfruttiamo il codice PHP per farci fare da lui il lavoro di estrazione dei file in automatico e metterli in una o più cartelle.

Ci mettiamo dunque al lavoro.

Partiamo dal presupposto di avere una tabella di DB del primo tipo descritto sopra, quella classica con dentro qualunque cosa.

Ora ci prepariamo una pagina php nuova in cui ci inseriamo il codice che ci serve per fare il processo in automatico così mi ritrovo la cartella bella pronta tutta riempita con i file di testo. Per farlo sfruttiamo le funzioni sulla gestione dei file che php mette a disposizione e che sono molto comode. La documentazione ufficiale su tutte le funzioni per la gestione dei file si trova qui (Filesystem Functions), un mio articolo precedente in cui parlo della scrittura di un file con il codice php si trova qui (Scrivere file di testo con script PHP a oggetti ), ora però dobbiamo adattare il tutto alle nostrre esigenze.

Ecco il codice della nostra paginetta php, il suo funzionamento è spiegato con i commenti lungo il codice, con queste premesse:

1-la tabella che ci interessa si chiama 'Tabella',

2- il suo contatore è 'idArticolo',

3-i testi che voglio estrarre sono nel campo 'titoloArticolo'

4-va costruita e messa sul server a mano una cartella vuota con il nome che ci serve in questo caso è 'titoloArticolo' (la scelta è ovviamente personale ma in queto modo il nome è autoesplicativo)

5- per evitare macelli si processa un solo campo alla volta, quindi i file vengono costruiti in una cartella alla volta, e per tutte le cartelle necessarie basta cambiare i codici della pagina e rimandarla in esecuzione sul server.

<?php

//classe che si occupa della scrittura dei file

class ScriviFile {
public function scriviTesto($percorsoNomeFile, $testo) {
$file = fopen($percorsoNomeFile, 'a+');//la funzone open prende vari parametri per decidere il tipo di permessi che si hanno sul file, in questo caso è a+, così crea il file anche se non esiste ancora e pone il pontatore alla fine del testo scritto
fwrite($file, $testo);
fclose($file);
}

};

//Connessione al database
//blocco dei parametri di connessione, ci vanno messi i dati forniti da chi ci gestisce il database
// nome di host
$host = "****";
// username dell'utente in connessione
$user = "*******";
// password dell'utente
$password = "******";
// nome del database
$db = "*******";

//stringa di connessione al DBMS
// istanza dell'oggetto della classe MySQLi
$mysqli = new mysqli($host, $user, $password, $db);

// verifica su eventuali errori di connessione
if ($mysqli->connect_errno) {
echo "Connessione fallita: ". $mysqli->connect_error . ".";
exit();
}

//ricavo i dati dalla tabella che mi interessa
$result = $mysqli->query("SELECT * FROM tabella ");//inserire qui il nome della tabella da cui prendere i dati

if($result->num_rows > 0) {
while($row = $result->fetch_array(MYSQLI_ASSOC)) //inserisco i dati estratti in un array
{
print_r ($row); //serve solo per la stampa di prova, non è obbligatorio ma utile, mi serve per vedere scritto l'array che ho ricavato e ridurre le quote di errore che puntualmente si verificano, magari solo per distrazione
echo '<br/>';//serve solo per vedere più facilmente i dati dell'array stampato
$idArticolo = $row['idArticolo']; //memorizzo il valore del campo idArticolo nella variabile con lo stesso nome, per evitare errori

$titoloArticolo = $row['titoloArticolo'];//idem come sopra

//cominciamo a lavorare seriamente alla scrittura dei file:

//l'oggetto objScriviFile che viene istanziato, prende due parametri in ingresso, uno è il percorso con il nome da dare al file, l'altro è la stringa che costituisce il testo da inserire nel file quindi ora ce li personalizziamo:

$nomeFile='titoloArticolo/titoloArticolo'.$idArticolo.'.txt';//qui devo costruire il percorso completo e dare il nome al file: quello che mi aspetto di ottenere è una cartella che si chiama titoloArticolo con dentro tanti file titoloArticolo1.txt, titoloArticolo2.txt ...ecc
$stringa=$titoloArticolo; //qui è il testo ricavato dalla tabella

//ora si costruisce l'oggetto che fa il lavoro di scrittura
$objScriviFile = new ScriviFile;
$objScriviFile->scriviTesto($nomeFile, $stringa);//tutto quanto è scritto qui si lascia inalterato perchè ho già personalizzato sopra

}

}
else {
echo 'nessun record presente'; }

// chiusura della connessione
$mysqli->close();
?>

Tutta questa paginona si sarebbe potuta sintetizzare inserendo la connessione la database come inclusione di file esterno come anche la classe ScriviFile posta all'inizio, ma per evitare piccoli errori di comprensione che poi andrebbero a pregiudicarne il funzionamento, ho preferito scriverla nel modo più esteso possibile.

Una volta scritta questa pagina php, la si scarica sul server in cui è residente il nostro bel sito e la si richiama dal browser mandandola così in esecuzione. Se tutto fila liscio, sulla pagina appariranno i dati dell'array senza alcuna indicazione di errore e andando a controllare la cartella che prima era vuota, adesso deve essere piena di file.

Se invece vengono indicati anche degli errori, significa che abbiamo avuto qualche distrazione nell'inserimento dei nomi di variabile: controllare SEMPRE l'utilizzo di maiuscole e minuscole, e anche se non si è capito un tubo di tutto quanto ho scritto qui, l'unica cosa che bisogna tener presente per estrarre i testi dal database in modo corretto sostituire in modo corretto i nomi che ho usato nell'esempio:

tabella --> mettere il nome della tabella da cui interessa estrarre i dati (riga 37 di questo codice)

IdArticolo --> mettere il nome del campo nel tabase che contiene il contatore della tabella (riga 44 e 52 di questo codice)

titoloArticolo --> mettere il nome del file che voglio ottenere e che concide con il nome della cartella vuota che conterrà tutti i file (riga 46, 52, 53 di questo codice)

Se finalmente tutto è andato in porto, ripetere la stessa operazione per tutte le cartelle che ci interessano, fatto questo finalmente possiamo pure buttare al secchio tutti i campi non più utili del nostro database.

Ora si deve fare attenzione su un punto: usando il parametro a+, si scrive il file e il puntatore si mette ALLA FINE del file, lo script fa il suo lavoro e siamo tutti contenti. Poi però c'è la variabile umana: capita che si mandi in esecuzione la pagina un'altra volta, magari solo perchè quel bastardo dell'autocompletamento degli indirizzi nel browser te la fa partire senza che uno non lo voglia effettivamente, e allora che succede? Il file in apertura viene già trovato pieno e si scrive di nuovo il testo partendo dalla coda del file, quindi se uno non ci pensa, si ritrova il testo estratto nel file duplicato tante volte quante è andato in esecuzione lo script. Per non complicarsi la vita basta eliminare il file php dal server dopo il suo utilizzo. Tutto qui.

powered by
Creativilab