Questo
post fa parte di una serie preparata qualche anno fa per
delle lezioni su PHP.
Moduli HTML: come non reinventare la ruota
Una delle cose più comuni nello sviluppo di applicazioni web è di dover predisporre dei moduli per l'inserimento di dati da parte dell'utente.Più di qualcuno si è cimentato nell'operazione di scrivere il codice HTML necessario, come ad esempio:
<form action="..." method="...">
<input type="text" name="id" value="12" />
</form>
Si tratta naturalmente di una pratica noiosa, passibile di errori, poco pratica rispetto alla manutenibilità del codice, ecc. e quindi, salvo casi particolari, da evitare.
Per non reinventare la ruota, esistono delle alternative:
- usare librerie di classi già pronte che permettono di generare i moduli
- usare framework che permettono generazione e gestione di moduli
Classi per la generazione di moduli
Tra le classi più popolari per la generazione di moduli, possiamo citare PEAR::HTML_QuickForm2 e UltimateForm.HTML_QuickForm2
La documentazione di queste classi non è ancora presente, ma ci si può basare sul codice sorgente, sulla documentazione di HTML_QuickForm e sulla bozza di API.L'esempio fornito con il pacchetto di installazione porta alla generazione di un modulo in cui compaiono gli elementi qui raffigurati:
Elementi generati con PEAR::HTML_QuickForm2 |
Fondamentalmente, per generare un modulo è necessario istanziare un oggetto di tipo HTML_QuickForm2, a cui dovremo agganciare i vari elementi, eventualmente raggruppati in fieldset.
require_once 'HTML/QuickForm2.php';
$form = new HTML_QuickForm2('picture');
$form->addDataSource(new HTML_QuickForm2_DataSource_Array(array(
'hiddenId' => $picture['id'],
'textDescription' => $picture['Description'],
'selCategory' => $picture['Category_id'],
'textPath' => $picture['Path'],
'textType' => $picture['Type'],
'textWidth' => $picture['Width'],
'textHeight' => $picture['Height'],
)));
$form->addElement('hidden', 'hiddenId');
$fsImage = $form->addElement('fieldset')->setLabel('Immagine');
$fsImage->addElement(
'text', 'textDescription', array('style' => 'width: 300px;'), array('label' => 'Descrizione:')
);
$fsImage->addElement(
'select', 'selCategory', null, array('options' => $categories, 'label' => 'Categoria:')
);
$fsFile = $form->addElement('fieldset')->setLabel('File');
$fsFile->addElement(
'text', 'textPath', array('style' => 'width: 200px;'), array('label' => 'Percorso:')
);
$fsFile->addElement(
'text', 'textType', array('style' => 'width: 200px;'), array('label' => 'Tipo:')
);
$fsPhoto = $form->addElement('fieldset')->setLabel('Foto');
$fsPhoto->addElement(
'text', 'textWidth', array('style' => 'width: 200px; text-align: right'), array('label' => 'Larghezza:')
);
$fsPhoto->addElement(
'text', 'textHeight', array('style' => 'width: 200px; text-align: right'), array('label' => 'Altezza:')
);
$fsActions = $form->addElement('fieldset')->setLabel('Azioni');
$btnReset = $fsActions->addElement(
'reset', 'btnReset', array('value' => 'Reimposta valori')
);
$btnSubmit = $fsActions->addElement(
'submit', 'btnSubmit', array('value' => 'Salva')
);
I dati da utilizzare per valorizzare i campi verranno probabilmente estratti da una base di dati, e dovremo decidere cosa fare alla ricezione del POST dell'utente. Il codice diventerà qualcosa di analogo al seguente:
<?php
/* model */
try
{
/*** connect to SQLite database ***/
$dbh = new PDO("sqlite2:pictures.sql.db");
$sql = "SELECT id, Description FROM Category ORDER BY RANK;";
$categories[' ']='--seleziona una categoria--';
foreach ($dbh->query($sql, PDO::FETCH_ASSOC) as $row)
{
$categories[$row['id']] = $row['Description'];
}
$stmt = $dbh->prepare("SELECT * FROM Picture where id = :id");
$stmt->bindParam(':id', $id);
$id = $_GET['id'];
if ($stmt->execute())
{
$picture = $stmt->fetch(PDO::FETCH_ASSOC);
}
}
catch(PDOException $e)
{
echo 'Error: ' . $e->getMessage() . "\n";
}
/* controller */
// vedi codice precedente
// decisione su cosa fare (se abbiamo avuto un post congeliamo il modulo)
if ('POST' == $_SERVER['REQUEST_METHOD'])
{
$submittedData=$form->getValue();
$fsActions->removeChild($btnReset);
$form->toggleFrozen(true);
}
/* view */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style type="text/css">
/* Set up custom font and form width */
body {
margin-left: 10px;
font-family: Arial,sans-serif;
font-size: small;
}
.quickform {
min-width: 500px;
max-width: 600px;
width: 560px;
}
/* Use default styles included with the package */
<?php readfile('data/quickform.css') ?>
</style>
<title>HTML_QuickForm2 example</title>
</head>
<body>
<?php
echo $form;
?>
<?php if ($form->toggleFrozen()): ?>
<p><a href="picture.php?id=<?php echo $id ?>">Modifica</a></p>
<?php endif ?>
<pre>
<?php print_r($picture) ?>
</pre>
</body>
</html>
Si dovrebbe ottenere un modulo simile a questo:
Esercizi
- Integrare l'uso di HTML_QuickForm2 nell'applicazione di gestione delle immagini, con la possibilità di modificare descrizione e categoria di appartenenza delle fotografie memorizzate nella base di dati.
- Gestire in maniera corretta il POST (con un redirect a una richiesta effettuata con metodo GET).
- Integrare HTML_QuickForm2 nella propria gerarchia di classi, in modo che per l'oggetto Picture sia possibile avere un metodo generateForm() o equivalente.
- Provare a usare le funzioni di validazione lato client e lato server.
- Provare altre classi per la generazione di moduli, come UltimateForm.
- Dare un'occhiata alla documentazione relativa alla gestione dei moduli in symfony, in particolare l'appendice riguardante iwidget disponibili.
Nessun commento:
Posta un commento