L'esempio trattato nel capitolo precedente riguarda il caso più semplice, cioé l'uso di una sola
tabella del database per salvare i risultati del form.
Ma è solo l'inizio. Nella realtà, una tabella può contenere valori numerici la cui descrizione
si trova in tabelle collegate di decodifica. Esempio: id_provincia, un numero cui corrisponde
la descrizione estesa nella tabella province. Anche in questo caso le condizioni possono variare,
a seconda che il database sia stato creato da noi o sia stato trovato già fatto. In entrambi i casi,
tuttavia, anche senza intercettare tali dipendenze nella struttura del database -tecnicamente possibile-
è sufficiente attenersi a semplici regole: intanto, si presuppone che il nome di un campo collegato a
tabella di decodifica sia un campo di tipo integer e inizi con un prefisso ID_, e che
il nome della tabella collegata e il nome del campo corrispondente seguano una logica.
Ad esempio: ID_PROVINCIA fa riferimento alla tabella PROVINCIA composta da un contatore e
un campo DESCRIZIONE. Quando il loop incontra nella tabella principale un campo di tipo integer
che inizia per
ID_, estrae dal nome del campo la parte restante, cerca la tabella con quel nome, ed esegue il loop dei
valori possibili.
Quindi, l'oggetto che rappresenta nel form fisicamente questa condizione sarà una
listbox (coppia id-descrizione) oppure una serie di pulsanti radio (si può stabilire
di ricorrere a questi ultimi quando i valori possibili non superano un certo limite).
Se ci troviamo in modalità modifica, l'attributo selected sarà posizionato
nell'id della tabella principale.
Come si vede, l'unico dato da passare al form perchè esso possa funzionare correttamente, è a
questo punto il nome della tabella.
Passiamo ora ad un caso più complesso, per sperimentare la
regola numero 3:
supponiamo che il form scriva non in una, ma in due tabelle
collegate con rapporto uno-a-molti, come ad esempio casa e camere.
Una visione semplicistica sarebbe portata a concepire un form principale per popolare la tabella principale,
per poi inserire, volta per volta e separatamente, i dati della tabella secondaria. Se a ciò si sommano le
funzionalità di modifica, il risultato sarebbe un incessante ping-pong tra files, convalide di dati,
connessioni al database, con il difetto non secondario di confondere l'utente.
Quindi, la via migliore è un unico form in un unico file.
Il primo passo è adattare il codice già creato per la tabella parent, in modo che possa
intercettare e gestire l'esistenza di una tabella child. Solo che questa informazione non è contenuta
nella tabella parent, che può sopravvivere anche senza dipendenze, ma nella tabella child,
che deve avere un campo con l'id univoco della riga corrispondente nel genitore.
I casi sono due: o si passa al form un secondo parametro, cioè il nome della tabella dipendente se esiste,
oppure si intercetta l'esistenza o meno di questa dipendenza. La prima soluzione, apparentemente più
ovvia, ci costringerebbe a rinunciare a un livello di astrazione quindi, in ossequio alla
regola numero 1
percorriamo la seconda.
In primo luogo occorre adottare una convenzione per il nome del campo con l'id del genitore nella
tabella child perché il ciclo possa riconoscere
questo tipo di dipendenza (esempio: parent_<nome della tabella genitore>).
Successivamente, si tratta di percorrere tutti i campi delle tabelle contenute nel database per cercarne
l'esistenza e, in caso affermativo, leggere il numero di righe (all'inizio sarà zero) e uscire dal ciclo.
A parole sembra macchinoso, ma per esperienza questo tipo di interrogazioni impiega tempi e risorse minimi.
Dobbiamo però stabilire
arbitrariamente un numero massimo per i children da aggiungere a quelli esistenti (all'inizio,
il numero massimo tout court); stabilire cioè
fin dall'inizio che ad una casa non possiamo mai aggiungere più di 50 camere per form
(se ci sono già 50 camere, altre 50 per volta in modalità modifica).
A questo punto, il codice già scritto per generare il form principale entra in funzione per
popolare il form con i campi presenti nella tabella child, tante volte quanto il numero
estratto dall'operazione precedente.
Anche in questo caso, dato che esso si differenzia dal precedente solo in questo dettaglio, evitiamo
il copia-incolla
(regola numero 7)
e adattiamo lo script precedente con gli array: per la tabella parent esso entrerà
in funzione una sola volta, producendo un solo valore per volta anziché un elemento di un array.
Quindi avremo un form con una sezione per i dati della casa, e 50 sezioni per quelli delle camere?
No: il ciclo, per ogni camera scriverà all'interno di un tag <div> settato con la proprietà
display:none e l'id numerato dall'array, e il form sarà dotato di una casella a discesa con valori da 1 al
numero massimo ricavato dall'operazione precedente (all'inizio, quindi, 50).
Questa casella a discesa permetterà di cambiare in run-time la visibilità
delle camere da utilizzare.
Non si tratta
di un artificio estetico: lo script di convalida questa volta non deve essere solo un loop tra i campi, ma
un array di loops (anch'esso non va riscritto, basta adattare quello
precedente). Il limite attivo di tale array altro non sarà che il valore selezionato nella listbox,
quindi esso agirà esclusivamente sui pannelli visibili al momento. La routine che costruisce
questi pannelli secondari è la stessa di quello principale; anche in questo caso ogni elemento prende
come name e id il nome del campo, ma tali nomi non saranno più elementi singoli,
bensì elementi di un array. In modalità modifica praticamente non cambia nulla,
poiché la
proprietà display assume il valore della listbox di controllo, la quale a sua volta,
invece di essere vuota o settata a 1 di default, assumerà il numero di righe della tabella
child corrispondenti alla tabella parent presenti al momento.
Quindi, in modalità aggiungi, l'utente vedrà un form per descrivere una casa, e
una listbox per indicare il numero di camere. Selezionando questo numero, e senza uscire dalla pagina,
avrà a disposizione tante sezioni quante sono le camere scelte.
In modalità modifica, vedrà i dati della casa e tante sezioni quante sono le camere
presenti, con la possibilità di aggiungerne altre o di toglierne qualcuna, sempre senza uscire
dalla pagina. Tutto questo in ottemperanza alla
regola numero 4.
|