More Related Content More from Manuel Baldassarri More from Manuel Baldassarri (8) Form refactoring1. PhpDay 2010 – 13 -15 maggio – Corropoli - Italy Form refactoring Il viaggio dei vecchi form verso il XXI secolo Manuel “Kea” Baldassarri 6. Code: 546 line of code <?php include("common.php"); require("header_html.php"); $print_form = true; if (isset($_POST['submitok'])) { $name = $_POST['name']; if (empty($name)) { error("Il campo nome è obbligatorio"); } if (strlen($name) < 2 && strlen($name) > 50) { error("Il campo nome non è valido"); } $surname = ucwords($_POST['surname']); if (!empty($name) && (strlen($surname) < 2) && strlen($surname) > 50) { error("Il campo cognome non è valido"); } $sesso = $_POST['sesso']; if (!empty($sesso) && $sesso != 'M' && $sesso != 'F') { error("Il campo sesso non è valido"); } $valid_mobile = true; $mobile = $_POST['mobile']; if (!empty($mobile) && !is_numeric($mobile)) { error("Il campo cellulare non è valido"); $valid_mobile = false; } $da = $_POST['da']; if ($da != 'sito' && $da != 'fuoridalsito') { error("Da dove sei arrivato"); } $valid_email = true; $email = $_POST['email']; if (($email != '') && !preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9_-]+)+$/", $email)) { error("Il campo email non è valido"); $valid_email = false; } $data_nasc = ($_POST['data_nasc']=='--')?0:$_POST['data_nasc']; $mese_nasc = ($_POST['mese_nasc']=='--')?0:$_POST['mese_nasc']; $anno_nasc = ($_POST['anno_nasc']=='--')?0:$_POST['anno_nasc']; $address = $_POST['address']; $cap = $_POST['cap']; $city = $_POST['city']; $provincia = $_POST['provincia']; $professione = $_POST['professione']; if (empty($email) && empty($mobile)) { error("Devi inserire il tuo indirizzo email o il numero del cellulare per procedere."); } dbConnect('phpday2010'); if (($email != '') && ($valid_email == true)) { $sql = "SELECT COUNT(*) FROM subscribers WHERE email = '$email' "; $result = mysql_query($sql); if (!$result) { error("A database error occurred."); } elseif (mysql_result($result, 0) > 0) { error("Un utente esiste già con l'email che hai inserito!"); } } if (($mobile != '') && ($valid_mobile == true)) { $sql = "SELECT COUNT(*) FROM subscribers WHERE mobile = '$mobile' "; $result = mysql_query($sql); if (!$result) { error("A database error occurred."); } elseif (mysql_result($result, 0) > 0) { error("Un utente esiste già con il cellulare che hai inserito!"); } } if (count($errors) == 0) { $data = date("Y-m-d H:i:s"); $sql = "INSERT INTO subscribers (name, surname, sesso, mobile, dove, email, quando, data_nasc, mese_nasc, anno_nasc, address, cap, city, provincia, professione) VALUES ('$name','$surname','$sesso','$mobile', '$dove','$email','$data','$data_nasc','$mese_nasc','$anno_nasc', '$address','$cap','$city','$provincia', '$professione')"; if (!mysql_query($sql)) { echo "A database error occurred in processing your submission.".mysql_error(); } else { if ($email == '') { $email = '***' . $mobile; } else { $msg = "Ciao $name, ti sei appena registrato sul sito TestRefactoring."; mail($email, 'Registrazione sito TestRefactoring', $msg, 'From: info@TestRefactoring.it'); } ?> <p>Ok! Sei iscritto con l'email <?php echo $email?>!</p> <?php $print_form = false; } } else { echo "<ul>"; foreach ($errors as $error) { echo "<li>$error</li>"; } echo "</ul>"; } } if ($print_form) { ?> <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <table> <tr> <td><label>Nome (*)</label></td> <td><input id="name" size="30" name="name" /></td> </tr> <tr> <td><label>Cognome</label></td> <td><input id="surname" size="30" name="surname" /> <font color="#ff6600"> </font></td> </tr> <tr> <td><label>Maschio/Femmina</label></td> <td> <input type="radio" value="M" name="sesso" /> Maschio <input type="radio" value="F" name="sesso" /> Femmina </td> </tr> <tr> <td><label>Data di nascita</label></td> <td> <select name="data_nasc" id="data_nasc"> <option selected="selected">--</option> <option value="01">01</option> <option value="02">02</option> <option value="03">03</option> <option value="04">04</option> <option value="05">05</option> <option value="06">06</option> <option value="07">07</option> <option value="08">08</option> <option value="09">09</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> <option value="13">13</option> <option value="14">14</option> <option value="15">15</option> <option value="16">16</option> <option value="17">17</option> <option value="18">18</option> <option value="19">19</option> <option value="20">20</option> <option value="21">21</option> <option value="22">22</option> <option value="23">23</option> <option value="24">24</option> <option value="25">25</option> <option value="26">26</option> <option value="27">27</option> <option value="28">28</option> <option value="29">29</option> <option value="30">30</option> <option value="31">31</option> </select> <select name="mese_nasc" id="mese_nasc"> <option selected="selected">-- </option> <option value="1">Gennaio </option> <option value="2">Febbraio </option> <option value="3">Marzo </option> <option value="4">Aprile </option> <option value="5">Maggio </option> <option value="6">Giugno </option> <option value="7">Luglio </option> <option value="8">Agosto </option> <option value="9">Settembre </option> <option value="10">Ottobre </option> <option value="11">Novembre </option> <option value="12">Dicembre</option> </select> <select name="anno_nasc" id="anno_nasc"> <option value="1900">1900</option> <option value="1901">1901</option> <option value="1902">1902</option> <option value="1903">1903</option> <option value="1904">1904</option> <option value="1905">1905</option> <option value="1906">1906</option> <option value="1907">1907</option> <option value="1908">1908</option> <option value="1909">1909</option> <option value="1910">1910</option> <option value="1911">1911</option> <option value="1912">1912</option> <option value="1913">1913</option> <option value="1914">1914</option> <option value="1915">1915</option> <option value="1916">1916</option> <option value="1917">1917</option> <option value="1918">1918</option> <option value="1919">1919</option> <option value="1920">1920</option> <option value="1921">1921</option> <option value="1922">1922</option> <option value="1923">1923</option> <option value="1924">1924</option> <option value="1925">1925</option> <option value="1926">1926</option> <option value="1927">1927</option> <option value="1928">1928</option> <option value="1929">1929</option> <option value="1930">1930</option> <option value="1931">1931</option> <option value="1932">1932</option> <option value="1933">1933</option> <option value="1934">1934</option> <option value="1935">1935</option> <option value="1936">1936</option> <option value="1937">1937</option> <option value="1938">1938</option> <option value="1939">1939</option> <option value="1940">1940</option> <option value="1941">1941</option> <option value="1942">1942</option> <option value="1943">1943</option> <option value="1944">1944</option> <option value="1945">1945</option> <option value="1946">1946</option> <option value="1947">1947</option> <option value="1948">1948</option> <option value="1949">1949</option> <option value="1950">1950</option> <option value="1951">1951</option> <option value="1952">1952</option> <option value="1953">1953</option> <option value="1954">1954</option> <option value="1955">1955</option> <option value="1956">1956</option> <option value="1957">1957</option> <option value="1958">1958</option> <option value="1959">1959</option> <option value="1960">1960</option> <option value="1961">1961</option> <option value="1962">1962</option> <option value="1963">1963</option> <option value="1964">1964</option> <option value="1965">1965</option> <option value="1966">1966</option> <option value="1967">1967</option> <option value="1968">1968</option> <option value="1969">1969</option> <option value="1970">1970</option> <option value="1971">1971</option> <option value="1972">1972</option> <option value="1973">1973</option> <option selected="selected">--</option> <option value="1974">1974</option> <option value="1975">1975</option> <option value="1976">1976</option> <option value="1977">1977</option> <option value="1978">1978</option> <option value="1979">1979</option> <option value="1980">1980</option> <option value="1981">1981</option> <option value="1982">1982</option> <option value="1983">1983</option> <option value="1984">1984</option> <option value="1985">1985</option> <option value="1986">1986</option> <option value="1987">1987</option> <option value="1988">1988</option> <option value="1989">1989</option> <option value="1990">1990</option> <option value="1991">1991</option> <option value="1992">1992</option> <option value="1993">1993</option> <option value="1994">1994</option> <option value="1995">1995</option> <option value="1996">1996</option> <option value="1997">1997</option> <option value="1998">1998</option> <option value="1999">1999</option> <option value="2000">2000</option> <option value="2001">2001</option> <option value="2002">2002</option> </select> </td> </tr> <tr> <td><label>Indirizzo</label></td> <td><input id="address" size="30" name="address" /></td> </tr> <tr> <td><label>CAP</label></td> <td><input id="cap" size="10" name="cap" /></td> </tr> <tr> <td><label>Località</label></td> <td><input id="city" size="30" name="city" /></td> </tr> <tr> <td><label>Provincia</label></td> <td><select name="provincia" id="provincia"> <option value="">-- Selezionare -- </option> <option value="AG">Agrigento (AG)</option> <option value="AL">Alessandria (AL)</option> <option value="AN">Ancona (AN)</option> <option value="AO">Aosta (AO)</option> <option value="AP">Ascoli Piceno (AP)</option> <option value="AQ">L'Aquila (AQ)</option> <option value="AR">Arezzo (AR)</option> <option value="AT">Asti (AT)</option> <option value="AV">Avellino (AV)</option> <option value="BA">Bari (BA)</option> <option value="BG">Bergamo (BG)</option> <option value="BI">Biella (BI)</option> <option value="BL">Belluno (BL)</option> <option value="BN">Benevento (BN)</option> <option value="BO">Bologna (BO)</option> <option value="BR">Brindisi (BR)</option> <option value="BS">Brescia (BS)</option> <option value="BZ">Bolzano (BZ)</option> <option value="CA">Cagliari (CA)</option> <option value="CB">Campobasso (CB)</option> <option value="CE">Caserta (CE)</option> <option value="CH">Chieti (CH)</option> <option value="CL">Caltanissetta (CL)</option> <option value="CN">Cuneo (CN)</option> <option value="CO">Como (CO)</option> <option value="CR">Cremona (CR)</option> <option value="CS">Cosenza (CS)</option> <option value="CT">Catania (CT)</option> <option value="CZ">Catanzaro (CZ)</option> <option value="EN">Enna (EN)</option> <option value="FC">Forlì-Cesena (FC)</option> <option value="FE">Ferrara (FE)</option> <option value="FG">Foggia (FG)</option> <option value="FI">Firenze (FI)</option> <option value="FR">Frosinone (FR)</option> <option value="GE">Genova (GE)</option> <option value="GO">Gorizia (GO)</option> <option value="GR">Grosseto (GR)</option> <option value="IM">Imperia (IM)</option> <option value="IS">Isernia (IS)</option> <option value="KR">Crotone (KR)</option> <option value="LC">Lecco (LC)</option> <option value="LE">Lecce (LE)</option> <option value="LI">Livorno (LI)</option> <option value="LO">Lodi (LO)</option> <option value="LT">Latina (LT)</option> <option value="LU">Lucca (LU)</option> <option value="MC">Macerata (MC)</option> <option value="ME">Messina (ME)</option> <option value="MI">Milano (MI)</option> <option value="MN">Mantova (MN)</option> <option value="MO">Modena (MO)</option> <option value="MS">Massa-Carrara (MS)</option> <option value="MT">Matera (MT)</option> <option value="NA">Napoli (NA)</option> <option value="NO">Novara (NO)</option> <option value="NU">Nuoro (NU)</option> <option value="OR">Oristano (OR)</option> <option value="PA">Palermo (PA)</option> <option value="PC">Piacenza (PC)</option> <option value="PD">Padova (PD)</option> <option value="PE">Pescara (PE)</option> <option value="PG">Perugia (PG)</option> <option value="PI">Pisa (PI)</option> <option value="PN">Pordenone (PN)</option> <option value="PO">Prato (PO)</option> <option value="PR">Parma (PR)</option> <option value="PT">Pistoia (PT)</option> <option value="PU">Pesaro e Urbino (PU)</option> <option value="PV">Pavia (PV)</option> <option value="PZ">Potenza (PZ)</option> <option value="RA">Ravenna (RA)</option> <option value="RC">Reggio Calabria (RC)</option> <option value="RE">Reggio Emilia (RE)</option> <option value="RG">Ragusa (RG)</option> <option value="RI">Rieti (RI)</option> <option value="RM">Roma (RM)</option> <option value="RN">Rimini (RN)</option> <option value="RO">Rovigo (RO)</option> <option value="SA">Salerno (SA)</option> <option value="SI">Siena (SI)</option> <option value="SO">Sondrio (SO)</option> <option value="SP">La Spezia (SP)</option> <option value="SR">Siracusa (SR)</option> <option value="SS">Sassari (SS)</option> <option value="SV">Savona (SV)</option> <option value="TA">Taranto (TA)</option> <option value="TE">Teramo (TE)</option> <option value="TN">Trento (TN)</option> <option value="TO">Torino (TO)</option> <option value="TP">Trapani (TP)</option> <option value="TR">Terni (TR)</option> <option value="TS">Trieste (TS)</option> <option value="TV">Treviso (TV)</option> <option value="UD">Udine (UD)</option> <option value="VA">Varese (VA)</option> <option value="VB">Verbano-Cusio-Ossola (VB)</option> <option value="VC">Vercelli (VC)</option> <option value="VE">Venezia (VE)</option> <option value="VI">Vicenza (VI)</option> <option value="VR">Verona (VR)</option> <option value="VT">Viterbo (VT)</option> <option value="VV">Vibo Valentia (VV)</option> <option value="EE">--Estero--</option> </select></td> </tr> <tr> <td><label>Cellulare (**)</label></td> <td>+39 <input id="mobile" maxlength="11" size="11" name="mobile" /> </td> </tr> <tr> <td><label>Email (**)</label></td> <td><input name="email" id="email" value="<?php echo $email ?>" size="30" /></td> </tr> <tr> <td><label>Professione</label></td> <td><table cellspacing="2" cellpadding="2" border="0"> <tbody> <tr> <td><input type="radio" value="altro" name="professione" /></td> <td>altro</td> <td><input type="radio" value="architetto" name="professione" /></td> <td>architetto</td> </tr> <tr> <td><input type="radio" value="artigiano" name="professione" /></td> <td>artigiano</td> <td><input type="radio" value="artista" name="professione" /></td> <td>artista</td> </tr> <tr> <td><input type="radio" value="avvocato" name="professione" /></td> <td>avvocato</td> <td><input type="radio" value="bancario" name="professione" /></td> <td>bancario</td> </tr> <tr> <td><input type="radio" value="commercialista" name="professione" /></td> <td>commercialista</td> <td><input type="radio" value="commerciante" name="professione" /></td> <td>commerciante</td> </tr> <tr> <td><input type="radio" value="dirigente" name="professione" /></td> <td>dirigente</td> <td><input type="radio" value="disoccupato" name="professione" /></td> <td>disoccupato</td> </tr> <tr> <td><input type="radio" value="impiegato" name="professione" /></td> <td>impiegato</td> <td><input type="radio" value="imprenditore" name="professione" /></td> <td>imprenditore</td> </tr> <tr> <td><input type="radio" value="ingegnere" name="professione" /></td> <td>ingegnere</td> <td><input type="radio" value="insegnante/docente" name="professione" /></td> <td>insegnante/docente</td> </tr> <tr> <td><input type="radio" value="libero professionista" name="professione" /></td> <td>libero professionista</td> <td><input type="radio" value="medico" name="professione" /></td> <td>medico</td> </tr> <tr> <td><input type="radio" value="non te lo dico" name="professione" /></td> <td>non te lo dico</td> <td><input type="radio" value="notaio" name="professione" /></td> <td>notaio</td> </tr> <tr> <td><input type="radio" value="operaio" name="professione" /></td> <td>operaio</td> <td><input type="radio" value="pensionato" name="professione" /></td> <td>pensionato</td> </tr> <tr> <td><input type="radio" value="programmatore" name="professione" /></td> <td>programmatore</td> <td><input type="radio" value="quadro" name="professione" /></td> <td>quadro</td> </tr> <tr> <td><input type="radio" value="responsabile it" name="professione" /></td> <td>responsabile it</td> <td><input type="radio" value="studente" name="professione" /></td> <td>studente</td> </tr> </tbody> </table> </td> </tr> <tr> <td colspan="2"> <strong>(*)</strong> Campi obbligatori<br /> <strong>(**)</strong> Il telefono o l'email sono obbligatorie<br /> <input type="submit" name="submitok" value="Invia" /> </td> </tr> </table> <input name="da" type="hidden" id="da" value="sito" /> </form> <?php } require("footer_html.php"); ?> 18. MVC architectural pattern Original code MODEL VIEW CONTROLLER Registration RegistrationUser RegitrationForm (validators) RegistrationView RegistrationForm (widgets) 19. View Spostare la vista in un altro file Sostituire “echo” e “print” con assegnazione di variabili e stamparle nella vista 20. View if ($print_form) { ?> <form action="<?php echo $_SERVER[... ... ... </form> <?php } require("footer_html.php"); ?> include "registration_view.php"; 21. Test kea@carminio selenium-tests $ phpunit TestSuite.php PHPUnit 3.4.3 by Sebastian Bergmann. ........ Time: 58 seconds, Memory: 9.58Mb Ok (8 tests, 21 assertions) Ok (8 tests, 21 assertions) 22. View echo "A database error occurred in processing your submission.".mysql_error(); $db_error = mysql_error(); <?php if (!empty($db_error)) : ?> A database error occurred in processing your submission. <?php echo $db_error ?> <?php endif ?> 23. Model Estraiamo tutto ciò che riguarda la rappresentazione della registrazione su database NO SQL nel controller 24. Model: store data $sql = "INSERT INTO registered_user (name, surname, ..., professione) VALUES ('$name', '$surname', ...,'$professione')"; if (!mysql_query($sql)) { $db_error = mysql_error(); } 25. Model: store data class RegisteredUser { public static function newFromArray(array $fields) { $sql = "INSERT INTO registered_user (name, surname, ..., professione) VALUES ('{$fields['name']}', ... '{$fields['professione']}')"; if (!mysql_query($sql)) { throw new Exception(mysql_error()); } } } 26. Model: store data $fields = array('name' => $name, … => …, 'professione' => $professione); try { RegisteredUser::newFromArray($fields); } catch (Exception $e) { $db_error = $e->getMessage(); } 27. Test kea@carminio selenium-tests $ phpunit TestSuite.php PHPUnit 3.4.3 by Sebastian Bergmann. ........ Time: 58 seconds, Memory: 9.58Mb Ok (8 tests, 21 assertions) Ok (8 tests, 21 assertions) 28. Model $sql = "SELECT COUNT(*) FROM registered_user WHERE email = '$email' "; $result = mysql_query($sql); if (!$result) { error("A database error occurred."); } elseif (mysql_result($result, 0) > 0) { error("Un utente esiste già con l'email che hai inserito!"); } 29. Model public static function findByEmail($value) { $result = mysql_query( "SELECT * FROM regitestered_user WHERE email = '$value'"); if (!$result) { throw new Exception(mysql_error()); } if (mysql_num_rows($result) == 0) { return null; } return mysql_fetch_assoc($result); } 30. Model try { $user = RegisteredUser::findByEmail($email); if (!is_null($user)) { error("Un utente esiste già con l'email che hai inserito!"); } } catch (Exception $e) { error("A database error occurred."); } 31. Test kea@carminio selenium-tests $ phpunit TestSuite.php PHPUnit 3.4.3 by Sebastian Bergmann. ........ Time: 58 seconds, Memory: 9.58Mb Ok (8 tests, 21 assertions) Ok (8 tests, 21 assertions) 32. Model Iteriamo fino a far scomparire dal controller tutto il codice SQL e riferimenti diretti al DB (mysql_*, pg_*, PDO*, ...) 34. Validators $name = $_POST['name']; if (empty($name)) { error("Il campo nome è obbligatorio"); } if (strlen($name) < 2 && strlen($name) > 50) { error("Il campo nome non è valido"); } 36. Validators public function bind($values) { $errors = array(); if (empty($values['name'])) { $errors[] = "Il campo nome è obbligatorio"; } if (strlen($name) < 2 && strlen($name) > 50) { $errors[] = "Il campo nome non è valido"; } . . . return $errors; } 37. Test kea@carminio selenium-tests $ phpunit TestSuite.php PHPUnit 3.4.3 by Sebastian Bergmann. ........ Time: 58 seconds, Memory: 9.58Mb Ok (8 tests, 21 assertions) Ok (8 tests, 21 assertions) 39. sfValidators sfValidatorString sfValidatorRegex sfValidatorEmail sfValidatorUrl sfValidatorInteger sfValidatorNumber sfValidatorBoolean sfValidatorChoice sfValidatorPass sfValidatorCallback sfValidatorDate sfValidatorTime sfValidatorDateTime sfValidatorDateRange sfValidatorFile sfValidatorAnd sfValidatorOr 40. sfValidators $nameValidator = new sfValidatorString( array('required' => true, 'max_length' => 50, 'min_length' => 2), array('required' => 'Il campo nome è obbligatorio', 'invalid' => 'Il campo nome non è valido')); $emailValidator = new sfValidatorEmail( array('required' => false), array('invalid' => 'Il campo email non è valido')), 41. sfValidators try { $name = $nameValidator->clean($name); } catch (sfValidatorError $e) { $error = $e->getMessage(); $is_valid = false; } 43. sfValidators public function bind($values) { $this->is_valid = true; $this->errors = array(); foreach ($this->validators as $name => $validator) { try { $this->values[$name] = $validator-> clean($values[$name]); } catch (sfValidatorError $e) { $this->values[$name] = $values[$name]; $this->addError($e->getMessage()); $this->is_valid = false; } } } 44. Test kea@carminio selenium-tests $ phpunit TestSuite.php PHPUnit 3.4.3 by Sebastian Bergmann. ........ Time: 58 seconds, Memory: 9.58Mb Ok (8 tests, 21 assertions) Ok (8 tests, 21 assertions) 46. sfWidgets sfWidgetFormChoice sfWidgetFormDate sfWidgetFormDateRange sfWidgetFormDateTime sfWidgetFormDoctrineChoice sfWidgetFormFilterInput sfWidgetFormFilterDate sfWidgetFormI18nChoiceCountry sfWidgetFormI18nChoiceLanguage sfWidgetFormI18nChoiceCurrency sfWidgetFormI18nChoiceTimezone sfWidgetFormI18nDate sfWidgetFormI18nDateTime sfWidgetFormI18nTime sfWidgetFormInput sfWidgetFormInputCheckbox sfWidgetFormInputFile sfWidgetFormInputFileEditable sfWidgetFormInputHidden sfWidgetFormInputPassword sfWidgetFormJQueryAutocompleter sfWidgetFormJQueryDate sfWidgetFormPropelChoice sfWidgetFormReCaptcha sfWidgetFormSchema sfWidgetFormSchemaDecorator sfWidgetFormSelect sfWidgetFormSelectDoubleList sfWidgetFormSelectMany sfWidgetFormSelectCheckbox sfWidgetFormSelectRadio sfWidgetFormTextarea sfWidgetFormTextareaTinyMCE sfWidgetFormTime 47. sfWidgets $gender = array('M' => 'M', 'F' => 'F'); $years = range(1900, 2002); $this->widgets = array( 'name' => new sfWidgetFormInputText(), 'sesso' => new sfWidgetFormChoice( array('choices' => self::$gender, 'expanded' => true)), 'da' => new sfWidgetFormInputHidden( array('default' => 'site')), 'anno_nasc' => new sfWidgetFormChoice( array('choices' => array_combine($years, $years))), ... ); 48. sfWidget <?php echo $nameWidget ?> <input type=”text” value=”default value” name=”form_name[name]” id=”form_name_name” /> 49. sfWidget <?php echo $nameWidget->renderRow() ?> <tr> <td> <label for=”form_name_name”>Label</label> <input … /> </td> </tr> 50. sfWidget: errors <?php echo $nameWidget->renderError(); ?> <ul class="error_list"> <li>Name: Required.</li> </ul> 51. sfForm class RegistrationForm extends sfForm { private $validators = array(); p rivate $widgets = array(); public function configure() { $this->setWidgets(array( 'name' => sfWidgetFormInputText(), … $this->setValidators(array( 'name' => sfValidatorString(...); … } } 52. View: 456 => 36 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <table> <?php echo $registration_form ?> <tr> <td colspan="2"> <input type="submit" name="submitok" value="Invia" /> </td> </tr> </table> </form> 53. Controller: 25 line left $form = new RegistrationForm(); if (isset($_POST['submitok'])) { $form-> bind ($_POST['registration']); $errors = $form-> getErrors (); if ($registration_form-> isValid ()) { $fields = $registration_form-> getValues (); $user = RegisteredUser :: newFromArray ($fields); try { $user-> save (); $user->sendRegistrationMail(); } catch (Exception $e) { $db_error = $e->message; } } } 60. Results registration.php (545) registrationForm.class.php (105) registrationUser.class.php (95) registration.class.php (33) registration.php (1) registrationView.php (36) Tot (270) 62. Credits Me [email_address] http://keasoft.it/blog Flickr: kea42 Twitter: k3a Anti if campaign http://www.antiifcampaign.com/ Foto http://www.flickr.com/photos/nikonand/3972068272/ http://www.flickr.com/photos/easyclick/4287695160/ http://www.flickr.com/photos/mrfink/3633775567/ http://cillitbang.co.uk Le altre sono mie ;) Editor's Notes Ingabbiare le applicazioni legacy con test funzionali (Selenium IDE + phpUnit). Ogni passaggio dal funzionale all'OOP scrivere unit test.