Development

Documentation/it_IT/book/forms/02-Form-Validation (diff)

You must first sign up to be able to contribute.

Changes between Version 1 and Version 2 of Documentation/it_IT/book/forms/02-Form-Validation

Show
Ignore:
Author:
garak (IP: 85.18.214.242)
Timestamp:
10/29/08 17:40:51 (8 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/it_IT/book/forms/02-Form-Validation

    v1 v2  
    9393 
    9494 
     95 
     96 
    9597  
    9698Usiamo tre diversi validatori: 
    222224>Il metodo `getValues()` restituisce un'array di tutti i dati validati e puliti. Ma se serve recuperare un solo valore, c'è anche il metodo `getValue()`: `$email = $this->form->getValue('email')`. 
    223225 
     226### Form non valida 
     227 
     228Ogni volta che ci sono campi non validi nella form, viene mostrato il template `indexSuccess`. La Figura 2-4 mostra cosa otteniamo quando inviamo una form con dati non validi. 
     229 
     230Figura 2-4 - Form non valida 
     231 
     232![Form non valida](http://www.symfony-project.org/images/forms_book/en/02_04.png "Form non valida") 
     233 
     234La chiamata al comando `<?php echo $form ?>` prende in considerazione automaticamente i messaggi di errore associati coi campi, e popolerà automaticamente i dati immessi dall'utente puliti. 
     235 
     236Quando la form è vincolata a dati esterni usando il metodo `bind()`, la form passa in uno stato vincolato e vengono attivate le seguenti azioni: 
     237 
     238  * Il processo di validazione viene eseguito 
     239  * I messaggi di errore sono memorizzati nella form per essere disponibili al template 
     240  * I valodi predefiniti della form sono sostituiti con quelli inviati dall'utente, puliti 
     241 
     242L'informazione necessaria a visualizzare i messaggi di errore o i dati utente sono facilmente disponibili usando la variabile `form` nel template. 
     243 
     244>**CAUTION** 
     245>Come visto nel Capitolo 1, possiamo passare dei valori predefiniti al costruttore della classe. Dopo l'invio di una form non valida, tali valori predefiniti sono sovrascritti dai valori inviati, in modo che l'utente possa correggere i suoi errori. Quindi non vanno mai usati i valori predefiniti, come in questo esempio: `$this->form->setDefaults($request->getParameter('contact'))`. 
     246 
     247Personalizzazione dei validatori 
     248-------------------------------- 
     249 
     250### Personalizzare i messaggi di errore 
     251 
     252Come forse hai notato nella Figura 2-4, i messaggi di errore non sono molto utili. Vediamo come personalizzarli per renderli più intuitivi. 
     253 
     254Ogni validatore può aggiungere errori alla form. Un errore consiste in un codice di errore ed in un messaggio di errore. Tutti i validatori hanno almeno gli errori `required` ed `invalid` definiti in `sfValidatorBase`: 
     255 
     256<table> 
     257  <tr> 
     258    <th>Codice</th> 
     259    <th>Messaggio</th> 
     260    <th>Descrizione</th> 
     261  </tr> 
     262  <tr> 
     263    <td><code>required</code></td> 
     264    <td>Required.</td> 
     265    <td>Il campo è obbligatorio ed il valore è vuoto</td> 
     266  </tr> 
     267  <tr> 
     268    <td><code>invalid</code></td> 
     269    <td>Invalid.</td> 
     270    <td>Il campo non è valido</td> 
     271  </tr> 
     272</table> 
     273 
     274Ecco i codici di errore associati ai validatori che abbiamo già usato: 
     275 
     276<table> 
     277  <tr> 
     278    <th>Validatore</th> 
     279    <th>Codici di errore</th> 
     280  </tr> 
     281  <tr> 
     282    <td>sfValidatorString</td> 
     283    <td><code>max_length</code></td> 
     284  </tr> 
     285  <tr> 
     286    <td></td> 
     287    <td><code>min_length</code></td> 
     288  </tr> 
     289  <tr> 
     290    <td>sfValidatorEmail</td> 
     291    <td></td> 
     292  </tr> 
     293  <tr> 
     294    <td>sfValidatorChoice</td> 
     295    <td></td> 
     296  </tr> 
     297</table> 
     298 
     299La personalizzazione dei messaggi di errore può essere fatta passando un secondo argomento durante la creazione degli oggetti di validazione. Il Listato 2-4 personalizza diversi messaggi di errore e la Figura 2-5 mostra i messaggi di errore personalizzati in azione. 
     300 
     301Listato 2-4 - Personalizzare i messaggi di errore 
     302 
     303    [php] 
     304    class ContactForm extends sfForm 
     305    { 
     306      protected static $subjects = array('Subject A', 'Subject B', 'Subject C'); 
     307      
     308      public function configure() 
     309      { 
     310        // ... 
     311      
     312        $this->setValidators(array( 
     313          'name'    => new sfValidatorString(array('required' => false)), 
     314          'email'   => new sfValidatorEmail(array(), array('invalid' => 'The email address is invalid.')), 
     315          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     316          'message' => new sfValidatorString(array('min_length' => 4), array('required' => 'The message field is required.')), 
     317        )); 
     318      } 
     319    } 
     320  
     321Figura 2-5 - Messaggi di errore personalizzati 
     322 
     323![Messaggi di errore personalizzati](http://www.symfony-project.org/images/forms_book/en/02_05.png "Messaggi di errore personalizzati") 
     324 
     325La Figura 2-6 mostra il messaggio di errore ottenuto se si prova ad inviare un messaggio troppo corto (abbiamo impostato la lunghezza minima a 4 caratteri). 
     326 
     327Figura 2-6 - Messaggio di errore per stringa troppo corta 
     328 
     329![Messaggio di errore per stringa troppo corta](http://www.symfony-project.org/images/forms_book/en/02_06.png "Messaggio di errore per stringa troppo corta") 
     330 
     331Il messaggio di errore predefinito relativo a questo codice di errore (`min_length`) è diverso dai messaggi che abbiamo già visto, poiché implementa due valori dinamici: i dati inseriti dall'utente (`foo`) ed il numero minimo di caratteri consentiti per questo campo (`4`). Il Listato 2-5 personalizza questo messaggio usando tali valori dinamici e la Figura 2-7 ne mostra il risultato. 
     332 
     333Listato 2-5 - Personalizzare i messaggi di errore con valori dinamici 
     334 
     335    [php] 
     336    class ContactForm extends sfForm 
     337    { 
     338      public function configure() 
     339      { 
     340        // ... 
     341      
     342        $this->setValidators(array( 
     343          'name'    => new sfValidatorString(array('required' => false)), 
     344          'email'   => new sfValidatorEmail(array(), array('invalid' => 'Email address is invalid.')), 
     345          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     346          'message' => new sfValidatorString(array('min_length' => 4), array( 
     347            'required'   => 'The message field is required', 
     348            'min_length' => 'The message "%value%" is too short. It must be of %min_length% characters at least.', 
     349          )), 
     350        )); 
     351      } 
     352    } 
     353  
     354Figura 2-7 - Messaggi di errore personalizzati con valori dinamici 
     355 
     356![Messaggi di errore personalizzati con valori dinamici](http://www.symfony-project.org/images/forms_book/en/02_07.png "Messaggi di errore personalizzati con valori dinamici") 
     357 
     358Ogni messaggio di errore può usare valori dinamici, includendo il nome del valore con un carattere di percentuale (`%`). I valori disponibili sono solitamente i dati inseriti dall'utente (`value`) e i valori delle opzioni del validatore relativo all'errore. 
     359 
     360>**TIP** 
     361>Se vuoi conoscere tutti i codici di errore, le opzioni, e i messaggi predefiniti di un validatore, fai riferimento alla documentazione online delle API (http://www.symfony-project.org/api/1_1/). Ogni codice, opzione e messaggio di errore è descritto in dettaglio, insieme con i valori predefiniti (per esempio, il l'API del validatore `sfValidatorString` è disponibile su http://www.symfony-project.org/api/1_1/sfValidatorString). 
     362 
     363Sicurezza dei validatori 
     364------------------------ 
     365 
     366Per default, una form è valida solo se ogni campo inviato dall'utente ha un validatore. Questo assicura che ogni campo ha le sue regole di validazione e che non è possibile inserire valori per campi che non sono definiti nella form. 
     367 
     368Per aiutare a caoure questo ruolo di sicurezza, consideriamo un oggetto `user` come mostrato nel Listato 2-6. 
     369 
     370Listato 2-6 - La classe `user` 
     371 
     372    [php] 
     373    class User 
     374    { 
     375      protected 
     376        $name = '', 
     377        $is_admin = false; 
     378      
     379      public function setFields($fields) 
     380      { 
     381        if (isset($fields['name'])) 
     382        { 
     383          $this->name = $fields['name']; 
     384        } 
     385      
     386        if (isset($fields['is_admin'])) 
     387        { 
     388          $this->is_admin = $fields['is_admin']; 
     389        } 
     390      } 
     391      
     392      // ... 
     393    } 
     394 
     395Un oggetto `User` è composto da due proprietà, il nome dell'utente (`name`), ed un booleano che memorizza lo stato di amministratore (`is_admin`). Il metodo `setFields()` aggiorna entrambe le proprietà. Il Listato 2-7 mostra la form relativa alla classe `User`, che consente all'utente di modificare solo la proprietà `name`. 
     396 
     397Listato 2-7 - Form per `User` 
     398 
     399    [php] 
     400    class UserForm extends sfForm 
     401    { 
     402      public function configure() 
     403      { 
     404        $this->setWidgets(array('name' => new sfWidgetFormInputString())); 
     405        $this->widgetSchema->setNameFormat('user[%s]'); 
     406      
     407        $this->setValidators(array('name' => new sfValidatorString())); 
     408      } 
     409    } 
     410 
     411Il listato 2-8 mostra un'implementazione del modulo `user` che usa la form definita sopra permettendo all'utente di modificare il campo `name`. 
     412 
     413Listato 2-8 - Implementazione del modulo `user` 
     414 
     415    [php] 
     416    class userActions extends sfActions 
     417    { 
     418      public function executeIndex($request) 
     419      { 
     420        $this->form = new UserForm(); 
     421      
     422        if ($request->isMethod('post')) 
     423        { 
     424          $this->form->bind($request->getParameter('user')); 
     425          if ($this->form->isValid()) 
     426          { 
     427            $user = // retrieving the current user 
     428      
     429            $user->setFields($this->form->getValues()); 
     430      
     431            $this->redirect('...'); 
     432          } 
     433        } 
     434      } 
     435    } 
     436 
     437Senza nessuna protezione, se l'utente invia una form con un valore per il campo `name`, ed insieme per il campo `is_admin`, allora il nostro codice è vulnerabile. Si può fare facilmente usando uno strumento come Firebug. Di fatto, il valore `is_admin` è sempre valido, perché il campo non ha un validatore associato nella form. Qualsiasi sia il valore, il metodo `setFields()` aggiornerà non solo la proprietà `name`, ma anche quella `is_admin`. 
     438 
     439Se verifichi questo codice passando un valore sia per `name` che per `is_admin`, otterai un errore globale "Extra field name.", come mostrato in Figura 2-8. Il sistema ha generato un errore perché alcuni campi inviati non hanno nessun validatore associato; il campo `is_admin` non è definito nella form `UserForm`. 
     440 
     441Figura 2-8 - Errore di validatore mancante 
     442 
     443![Errore di validatore mancante](http://www.symfony-project.org/images/forms_book/en/02_08.png "Errore di validatore mancante") 
     444 
     445Tutti i validatori che abbiamo visto finora generano errori associati a campi. Da dove viene questo errore globale? Quando usiamo il metodo `setValidators()`, symfony crea un oggetto `sfValidatorSchema`. `sfValidatorSchema` definisce un insieme di validatori. La chiamata a `setValidators()` è equivalente al seguente codice: 
     446 
     447    [php] 
     448    $this->setValidatorSchema(new sfValidatorSchema(array( 
     449      'email'   => new sfValidatorEmail(), 
     450      'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     451      'message' => new sfValidatorString(array('min_length' => 4)), 
     452    ))); 
     453  
     454`sfValidatorSchema` ha due regole di validazione abilitate di default per proteggere l'insieme di validatori. Tali regole possono essere configurate con le opzioni `allow_extra_fields` e `filter_extra_fields`. 
     455 
     456L'opzione `allow_extra_fields`, impostata a `false` di default, verifica che ogni dato inviato dall'utente abbia un validatore. Se non è così, viene lanciato un errore globale "Extra field name.", come mostrato nell'esempio precedente. Qesto consente agli sviluppatori di essere avvertiti se si dimenticano di validare espressamente un campo. 
     457 
     458Torniamo alla form `contact`. Cambiamo le regole di validazione modificando il campo `name` in un campo obbligatorio. Poiché il valore predefinito dell'opzione `required` è `true`, possiamo cambiare il validatore `name` in: 
     459 
     460    [php] 
     461    $nameValidator = new sfValidatorString(); 
     462 
     463Questo validatore non ha impatto poiché non ha né l'opzione `min_length` né quella `max_length`. In tal caso, possiamo anche sostituirlo con un validatore vuoto: 
     464 
     465    [php] 
     466    $nameValidator = new sfValidatorPass(); 
     467 
     468Invece di definire un validatore vuoto, possiamo farne a meno, ma la protezione di default che abbiamo visto prima ce lo impedisce. Il Listato 2-9 mostra come disabilitare la protezione usando l'opzione `allow_extra_fields`. 
     469 
     470Listato 2-9 - Disabilitare la protezione `allow_extra_fields` 
     471 
     472    [php] 
     473    class ContactForm extends sfForm 
     474    { 
     475      public function configure() 
     476      { 
     477        // ... 
     478      
     479        $this->setValidators(array( 
     480          'email'   => new sfValidatorEmail(), 
     481          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     482          'message' => new sfValidatorString(array('min_length' => 4)), 
     483        )); 
     484      
     485        $this->validatorSchema->setOption('allow_extra_fields', true); 
     486      } 
     487    } 
     488 
     489Dovresti ora poter validare la form come mostrato in Figura 2-9. 
     490 
     491Figura 2-9 - Validazione con `allow_extra_fields` impostato a `true` 
     492 
     493![Validazione con `allow_extra_fields` impostato a `true`](http://www.symfony-project.org/images/forms_book/en/02_09.png "Validazione con `allow_extra_fields` impostato a `true`") 
     494 
     495Se guardi meglio, noterai che anche se la form è valida, il valore del campo `name` è vuoto nella pagina di ringraziamento, indipendentemente da qualsiasi valore che sia stato inviato. Di fatto, il valore non è stato nemmeno impostato nell'array inviata da `$this->form->getValues()`.  Disabilitare l'opzione `allow_extra_fields` ci consente di liberarci dell'errore dovuto alla mancanza di un validatore, ma l'opzione `filter_extra_fields`, impostata a `true` di default, filtra tali valori, rimuovendoli dai valori validati. Ovviamente è possibile cambiare questo comportamento, come mostrato nel Listato 2-10. 
     496 
     497Listato 2-10 - Disabilitare la protezione `filter_extra_fields` 
     498 
     499    [php] 
     500    class ContactForm extends sfForm 
     501    { 
     502      public function configure() 
     503      { 
     504        // ... 
     505      
     506        $this->setValidators(array( 
     507          'email'   => new sfValidatorEmail(), 
     508          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     509          'message' => new sfValidatorString(array('min_length' => 4)), 
     510        )); 
     511      
     512        $this->validatorSchema->setOption('allow_extra_fields', true); 
     513        $this->validatorSchema->setOption('filter_extra_fields', false); 
     514      } 
     515    } 
     516 
     517Dovresti ora poter validare la tua form e recuperare il valore inviato nella pagina di ringraziamento. 
     518 
     519Nel Capitolo 4 vedremo che queste protezioni possono essere usate per serializzare in sicurezza degli oggetti Propel da valori della form. 
     520 
     521Validatori logici 
     522------------------ 
     523 
     524Diversi validatori possono essere definiti per un singolo campo, usando i validatori logici: 
     525 
     526  * `sfValidatorAnd`: Per essere valido, il campo deve passare tutti i validatori 
     527  * `sfValidatorOr` : Per essere valido, il campo deve passare almeno un validatore 
     528 
     529I costruttori degli operatori logici accettano una lista di validatori come primo argomento. Il Listato 2-11 usa `sfValidatorAnd` per associare due validatori richiesti al campo `name`. 
     530 
     531Listato 2-11 - Uso del validatore `sfValidatorAnd` 
     532 
     533    [php] 
     534    class ContactForm extends sfForm 
     535    { 
     536     public function configure() 
     537     { 
     538        // ... 
     539      
     540        $this->setValidators(array( 
     541          // ... 
     542          'name' => new sfValidatorAnd(array( 
     543            new sfValidatorString(array('min_length' => 5)), 
     544            new sfValidatorRegex(array('pattern' => '/[\w- ]+/')), 
     545          )), 
     546        )); 
     547      } 
     548    } 
     549 
     550Quando si invia la form, i dati inseriti nel campo `name` devo avere almeno cinque caratteri e soddisfare l'espressione regolare `([\w- ]+)`. 
     551 
     552Essendo i validatori logici dei validatori essi stessi, possono essere combinati per definire delle espressioni logiche avanzate, come mostrato nel Listato 2-12. 
     553 
     554Listato 2-12 - Combinare diversi operatori logici 
     555 
     556    [php] 
     557    class ContactForm extends sfForm 
     558    { 
     559     public function configure() 
     560     { 
     561        // ... 
     562      
     563        $this->setValidators(array( 
     564          // ... 
     565          'name' => new sfValidatorOr(array( 
     566            new sfValidatorAnd(array( 
     567              new sfValidatorString(array('min_length' => 5)), 
     568              new sfValidatorRegex(array('pattern' => '/[\w- ]+/')), 
     569            )), 
     570            new sfValidatorEmail(), 
     571          )), 
     572        )); 
     573      } 
     574    } 
     575  
     576Validatori globali 
     577------------------ 
     578 
     579Ogni validatore visto finora è associato con uno specifico campo e ci consente di validare solo un campo alla volta. Per default, si comportano ignorando ogni altro dato inviato dall'utente, ma talvolta la validazione di un campo dipende dal contesto o dipende da molti altri campi. Per esempio, serve un validatore globale quando due password devono coincidere, oppure quando una data d'inizio deve essere antecedente ad una data di fine. 
     580 
     581In entrambi questi casi, dobbiamo usare un validatore globale per validare i dati inviati dall'utente nel loro contesto. Possiamo memorizzare un validatore globlae prima o dopo la validazione individuale dei campi, usando rispettivamente un pre-validatore o un post-validatore. Di solito è meglio usare un post-validatore, perché i dati sono già stati validati e puliti, cioè sono in un formato normalizzato. Il Listato 2-13 mostra come implementare il confronto di due password usando il validatore `sfValidatorSchemaCompare`. 
     582 
     583Listato 2-13 - Usare il validatore `sfValidatorSchemaCompare` 
     584 
     585  [php] 
     586  $this->validatorSchema->setPostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again')); 
     587  
     588>**TIP** 
     589>La classe `sfValidatorSchemaCompare` eredita dal validatore `sfValidatorSchema`. `sfValidatorSchema` è esso stesso un validatore globale, poiché valida  tutti i dati inviati dall'utente, passando agli altri validatori la validazione di ogni campo. 
     590 
     591Il Listato 2-14 mostra come usare un singolo validatore per validare una data di inizio che debba essere antecedente ad una data di fine, personalizzando il messaggio di errore. 
     592 
     593Listato 2-14 - Usare il validatore `sfValidatorSchemaCompare` 
     594 
     595    [php] 
     596    $this->validatorSchema->setPostValidator( 
     597      new sfValidatorSchemaCompare('start_date', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'end_date', 
     598        array(), 
     599        array('invalid' => 'La data di inizio ("%left_field%") deve essere antecedente alla data di fine ("%right_field%")') 
     600      ) 
     601    ); 
     602 
     603L'uso di un post-validatore assicura che il confronto delle due date sarà accurato. Qualsiasi formato di data venga usato dall'utente, la validazione dei campi `start_date` ed `end_date` sarà sempre convertito in un formato comparabile (di default `Y-m-d H:i:s`). 
     604 
     605Per default, i pre-validatori ed i post-validatori restituiscono errori globali alla form. Tuttativa, alcuni di essi possono associare un errore ad un campo specifico. Per esempio, l'opzione `throw_global_error` del validatore `sfValidatorSchemaCompare` può scegliere tra un errore globale (Figura 2-10) o un errore associato al primo campo (Figura 2-11). Il Listato 2-15 mostra come usare l'opzione `throw_global_error`. 
     606 
     607Listato 2-15 - Usare l'opzione `throw_global_error` 
     608 
     609    [php] 
     610    $this->validatorSchema->setPostValidator( 
     611      new sfValidatorSchemaCompare('start_date', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'end_date', 
     612        array('throw_global_error' => true), 
     613        array('invalid' => 'The start date ("%left_field%") must be before the end date ("%right_field%")') 
     614      ) 
     615    ); 
     616 
     617Figure 2-10 - Errore globale per un validatore globale 
     618 
     619![Errore globale per un validatore globale](http://www.symfony-project.org/images/forms_book/en/02_10.png "Errore globale per un validatore globale") 
     620 
     621Figure 2-11 - Errore locale per un validatore locale 
     622 
     623![Errore locale per un validatore locale](http://www.symfony-project.org/images/forms_book/en/02_11.png "Errore locale per un validatore locale") 
     624 
     625Infine, l'uso di un validatore logico ti consente di combinare diversi post-validatori, come mostrato nel Listato 2-16. 
     626 
     627Listato 2-16 - Combinare diversi post-validatori con un validatore logico 
     628 
     629    [php] 
     630    $this->validatorSchema->setPostValidator(new sfValidatorAnd(array( 
     631      new sfValidatorSchemaCompare('start_date', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'end_date'), 
     632      new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again'), 
     633    ))); 
     634 
     635Invio di file  
     636------------- 
     637 
     638Trattare gli invii di file in PHP, come in ogni altro linguaggio orientato al web, coinvolge la gesione sia del codice HTML che del file lato server. In questa sezione vedremo gli strumenti che il framework offre allo sviluppatore per rendergli la vita più facile. Vedremo anche come non cadere in alcune trappole comuni. 
     639 
     640Cambiamo la form `contact` per consentire di inserire un file da allegare al messaggio. Per farlo, aggiungere un campo `file`, come mostrato nel Listato 2-17. 
     641 
     642Listato 2-17 - Aggiungere un campo `file` alla form `ContactForm` 
     643 
     644    [php] 
     645    // lib/form/ContactForm.class.php 
     646    class ContactForm extends sfForm 
     647    { 
     648      protected static $subjects = array('Subject A', 'Subject B', 'Subject C'); 
     649      
     650      public function configure() 
     651      { 
     652        $this->setWidgets(array( 
     653          'name'    => new sfWidgetFormInput(), 
     654          'email'   => new sfWidgetFormInput(), 
     655          'subject' => new sfWidgetFormSelect(array('choices' => self::$subjects)), 
     656          'message' => new sfWidgetFormTextarea(), 
     657          'file'    => new sfWidgetFormInputFile(), 
     658        )); 
     659        $this->widgetSchema->setNameFormat('contact[%s]'); 
     660      
     661        $this->setValidators(array( 
     662          'name'    => new sfValidatorString(array('required' => false)), 
     663          'email'   => new sfValidatorEmail(), 
     664          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))), 
     665          'message' => new sfValidatorString(array('min_length' => 4)), 
     666          'file'    => new sfValidatorFile(), 
     667        )); 
     668      } 
     669    } 
     670  
     671Quando in una form c'è un widget `sfWidgetFormInputFile` chje consente l'invio di un file, dobbiamo anche aggiungere l'attributo `enctype` al tag `form`, come mostrato nel Listato 2-18. 
     672 
     673Listato 2-18 - Modificare il template per considerare il campo `file` 
     674 
     675    <form action="<?php echo url_for('contact/index') ?>" method="post" enctype="multipart/form-data"> 
     676      <table> 
     677        <?php echo $form ?> 
     678        <tr> 
     679          <td colspan="2"> 
     680            <input type="submit" /> 
     681          </td> 
     682        </tr> 
     683      </table> 
     684    </form> 
     685  
     686>**NOTE** 
     687> Se generi dinamicamente il template associato alla form, il metodo `isMultipart()` dell'oggetto `form` restituisce `true`, nel caso in cui ci sia bisogno dell'attributo `enctype`. 
     688 
     689PHP non memorizza le informazioni sui file caricati insieme agli altri valori. Quindi è necessario modificare la chiamata al metodo `bind()` per passare questa informazione come secondo argomento, come mostrato nel Listato 2-19. 
     690 
     691Listato 2-19 - Passare i file caricati al metodo `bind()` 
     692 
     693    [php] 
     694    class contactActions extends sfActions 
     695    { 
     696      public function executeIndex($request) 
     697      { 
     698        $this->form = new ContactForm(); 
     699      
     700        if ($request->isMethod('post')) 
     701        { 
     702          $this->form->bind($request->getParameter('contact'), $request->getFiles('contact')); 
     703          if ($this->form->isValid()) 
     704          { 
     705            $values = $this->form->getValues(); 
     706            // do something with the values 
     707      
     708            // ... 
     709          } 
     710        } 
     711      } 
     712      
     713      public function executeThankyou() 
     714      { 
     715      } 
     716    } 
     717 
     718Ora che la form è pienamente operativa, abbiamo ancora bisogno di cambiare l'azione per memorizzare il file su disco. Come abbiamo osservato all'inizio di questo capitolo, `sfValidatorFile` converte le informazioni relative al file caricato in un oggetto `sfValidatedFile`. Il Listato 2-20 mostra come gestire tale oggetto per memorizzare il file nella cartella `web/uploads`. 
     719 
     720Listato 2-20 - Usare l'oggetto `sfValidatedFile` 
     721 
     722    [php] 
     723    if ($this->form->isValid()) 
     724    { 
     725      $file = $this->form->getValue('file'); 
     726      
     727      $filename = 'uploaded_'.sha1($file->getOriginalName()); 
     728      $extension = $file->getExtension($file->getOriginalExtension()); 
     729      $file->save(sfConfig::get('sf_upload_dir').'/'.$filename.$extension); 
     730      
     731      // ... 
     732    } 
     733 
     734La seguente tabella elenca tutti i metodi dell'oggetto `sfValidatedFile`: 
     735 
     736<table> 
     737  <tr> 
     738    <th>Metodo</th> 
     739    <th>Descrizione</th> 
     740  </tr> 
     741  <tr> 
     742    <td>save()</td> 
     743    <td>Salva il file caricato</td> 
     744  </tr> 
     745  <tr> 
     746    <td>isSaved()</td> 
     747    <td>Restituisce <code>true</code> se il file è stato salvato</td> 
     748  </tr> 
     749  <tr> 
     750    <td>getSavedName()</td> 
     751    <td>Restituisce il nome del file salvato</td> 
     752  </tr> 
     753  <tr> 
     754    <td>getExtension()</td> 
     755    <td>Restituisce l'estensione del file salvato, a seconda del tipo mime</td> 
     756  </tr> 
     757  <tr> 
     758    <td>getOriginalName()</td> 
     759    <td>Restituisce il nome del file caricato</td> 
     760  </tr> 
     761  <tr> 
     762    <td>getOriginalExtension()</td> 
     763    <td>Restituisce l'estensione del file caricato</td> 
     764  </tr> 
     765  <tr> 
     766    <td>getTempName()</td> 
     767    <td>Restituisce il percorso del file temporaneo</td> 
     768  </tr> 
     769  <tr> 
     770    <td>getType()</td> 
     771    <td>Restiuisce il tipo mime del file</td> 
     772  </tr> 
     773  <tr> 
     774    <td>getSize()</td> 
     775    <td>Restituisce la dimensione del file</td> 
     776  </tr> 
     777</table> 
     778 
     779>**TIP** 
     780>Il tipo mime fornito dal browser durante il caricamento del file non è affidabile. Per assicurare la massima sicurezza, durante la validazione vengono usati le funzione `finfo_open` e `mime_content_type`, e lo strumento `file`. Come ultima risorsa, se nessuna delle funzioni riesce a ricavare il tipo mime, o se il sistema non lo fornisce, viene considerato il tipo mime del browser. Per modificare le funzioni che ricavano il tipo mime, basta passare l'opzione `mime_type_guessers` al costruttore `sfValidatorFile`. 
     781 
    224782}}}