Development

Documentation/pl_PL/forms (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of Documentation/pl_PL/forms

Show
Ignore:
Author:
pawel (IP: 145.237.109.122)
Timestamp:
09/17/09 11:37:22 (8 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/pl_PL/forms

    v0 v1  
     1{{{ 
     2#!WikiMarkdown 
     3 
     4Rozdział 1 - tworzenie formularzy 
     5========================= 
     6 
     7Formularz składa się np. z takich pól jak hidden, text, select czy pola wyboru (checkboxes). Niniejszy rozdział stanowi wprowadzenie do tworzenia formularzy i zarządzania polami formularza za pomocą symfony form framework. 
     8 
     9Symfony 1.1 wymaga zastosowania się do rozdziałów tej książki. Będziesz również potrzebował stworzyć projekt i `frontend` projektu.  
     10W celu uzyskania więcej informacji na temat tworzenia projektu symfony proszę odnieść się do dokumentacji głównej. 
     11 
     12Zanim zaczniemy 
     13--------------- 
     14 
     15Zaczniemy dodając formularz kontaktowy do aplikacji symfony. 
     16 
     17Rysunek 1-1 pokazuje formularz kontaktowy z punktu widzenia użytkowników, którzy chcą wysłać wiadomość. 
     18 
     19Rysunek 1-1 - formularz kontaktowy 
     20 
     21![Contact form](/images/forms_book/en/01_01.png "Contact form") 
     22![Contact form](http://trac.symfony-project.org/browser/doc/branches/1.2/forms/images/en/01_01.png "Contact form") 
     23 
     24Stworzymy trzy pola na potrzeby tego formularza: nazwa użytkownika, adres email użytkownika i wiadomość, którą użytkownik chce wysłać. Będziemy po prostu wyświetlać informacje przesłane w formularzu dla celów tego ćwiczenia, tak jak pokazano na rys. 1-2. 
     25 
     26Rysunek 1-2 - Strona z podziękowaniem 
     27 
     28![Thank you page](/images/forms_book/en/01_02.png "Thank you page") 
     29 
     30Rysunek 1-3 - Interakcje między aplikacją a użytkownikiem 
     31 
     32![Interaction with the user schema](/images/forms_book/en/01_03.png "Interaction with the user schema") 
     33 
     34 
     35Widżety 
     36------- 
     37 
     38### Klasy `SfForm` i `sfWidget`  
     39 
     40Użytkownicy wpisują dane w celu wypełnienia formularza. W Symfony, formularz jest obiektem dziedziczącym z klasy `sfForm`. W naszym przykładzie, stworzymy `Formularz kontaktowy` dziedziczący z klasy `sfForm`. 
     41 
     42>**Note** 
     43>`sfForm` jest klasą bazową wszystkich formularzy i ułatwia konfigurację oraz zarządzanie formularzem. 
     44 
     45Możesz zacząć konfigurować Twój formularz dodając **widżety** za pomocą metody `configure()`. 
     46 
     47**Widżet** reprezentuje pole formularza. W naszym przykładzie, musimy dodać trzy widżety reprezentujące nasze trzy pola: `Imię`, `email` oraz `wiadomość`.  
     48Listing 1-1 przedstawia pierwszą implementację klasy `ContactForm`. 
     49 
     50Listing 1-1 - Klasa `ContactForm` z trzema polami 
     51 
     52    [php] 
     53    // lib/form/ContactForm.class.php 
     54    class ContactForm extends sfForm 
     55    { 
     56      public function configure() 
     57      { 
     58        $this->setWidgets(array( 
     59          'name'    => new sfWidgetFormInput(), 
     60          'email'   => new sfWidgetFormInput(), 
     61          'message' => new sfWidgetFormTextarea(), 
     62        )); 
     63      } 
     64    } 
     65 
     66 
     67>**NOTE** 
     68>W tej książce, nigdy nie deklarujemy `<?php` w kodzie  
     69>przykładów, zamieszcamy wyłącznie czysty kod PHP w celu optymalizacji przestrzeni i ochrony 
     70>paru drzew. Należy oczywiście pamiętać, aby dodać tą deklarację podczas tworzenia 
     71>nowego pliku PHP. 
     72 
     73Widżety są zdefiniowane w metodzie `configure()`. Metoda ta jest wywoływana automatycznie przez konstruktora klasy `sfForm`. 
     74 
     75Metoda `setWidgets()` jest stosowana do definiowania widżetów zastosowanych w formularzu. Metoda `setWidgets()` akceptuje tablicę asocjacyjną, gdzie kluczami są nazwy pól, a wartościami obiekty widżetu. Każdy widżet jest obiektem dziedziczącym po klasie `sfWidget`. W tym przykładzie użyliśmy dwóch typów widżetów: 
     76 
     77   * `sfWidgetFormInput`: Ten widżet reprezentuje pole `input` 
     78   * `sfWidgetFormTextarea`: Ten widżet reprezentuje pole `textarea` 
     79 
     80>**Note** 
     81>Standardowo klasy formularzy przechowywane są w katalogu `lib/form/`. Możesz przechowywać je w dowolnym katalogu zarządzanym przez mechanizm autoloading'u, ale jak zobaczysz później, symfony używa katalog `lib/form/` do generowania formularzy z modelu obiektów. 
     82 
     83### Wyświetlanie formularza 
     84 
     85Nasz formularz jest teraz gotowy do użycia. Możemy teraz utworzyć moduł symfony do wyświetlania formularza:     
     86     
     87    $ cd ~/PATH/TO/THE/PROJECT 
     88    $ php symfony generate:module frontend contact 
     89     
     90W module `contact`, zmieńmy akcję `index` tak aby przejść do template'ki formularza tak jak pokazano na Listingu 1-2. 
     91 
     92Listing 1-2 - Klasa Actions Modułu `contact`     
     93 
     94    [php] 
     95    // apps/frontend/modules/contact/actions/actions.class.php 
     96    class contactActions extends sfActions 
     97    { 
     98      public function executeIndex() 
     99      { 
     100        $this->form = new ContactForm(); 
     101      } 
     102    } 
     103     
     104Przy tworzeniu formularza, metoda `configure()`, zdefiniowana wcześniej, będzie wywoływana automatycznie. 
     105 
     106My po prostu musimy teraz stworzyć template, aby wyświetlić formularz w sposób pokazany na listingu 1-3. 
     107 
     108Listing 1-3 - Template do wyświetlania formularza     
     109 
     110    [php] 
     111    // apps/frontend/modules/contact/templates/indexSuccess.php 
     112    <form action="<?php echo url_for('contact/submit') ?>" method="POST"> 
     113      <table> 
     114        <?php echo $form ?> 
     115        <tr> 
     116          <td colspan="2"> 
     117            <input type="submit" /> 
     118          </td> 
     119        </tr> 
     120      </table> 
     121    </form> 
     122 
     123 
     124Formularz Symfony za pomocą widżetów wyświetla jedynie informacje dla użytkowników. W template `indexSuccess` linia `<?php echo $form?>` wyświetla jedynie trzy pola. Inne elementy, takie jak tagi formularza oraz przycisk zatwierdzający wysłanie, będą musiały być dodawane przez developera. To może nie jest zbyt oczywiste na początku, ale zobaczymy później, jak przydatne i proste jest zarządzanie formularzami. 
     125 
     126Korzystanie z konstrukcji `<?php echo $form?>` jest bardzo przydatne przy tworzeniu prototypów i definiowaniu formularzy. To pozwala programistom skupić się na logice biznesowej, nie martwiąc się o aspekty wizualne. Rozdział trzeci wyjaśni, jak personalizować template i layout formularza. 
     127 
     128>**Note** 
     129Podczas wyświetlania obiektu za pomocą `<? php echo $form ?>`, silnik PHP wyświetlia tekstową reprezentację obiektu `$form`. Chcąc przekonwertować obiekt na ciąg znaków, PHP próbuje wykonać metodę magiczną `__toString()`. Każdy widżet implementuje magiczną metodę przekształcenia obiektu w kod HTML. Wywołanie `<?php echo $form ?>` jest o równoważne z wywołaniem `<?php echo $form-> __toString()?>`. 
     130 
     131Możemy teraz zobaczyć formularz w przeglądarce (rys. 1-4) i sprawdzić wynik, wywołując akcję `contact/index` (`/frontend_dev.php/contact`). 
     132 
     133Rysunek 1-4 - Wygenerowany formularz kontaktowy 
     134 
     135![Generated Contact Form](/images/forms_book/en/01_04.png "Generated Contact Form") 
     136 
     137Listing 1-4 Pokazuje kod wygenerowany przez template. 
     138 
     139    [html] 
     140    <form action="/frontend_dev.php/contact/submit" method="POST"> 
     141      <table> 
     142         
     143        <!-- Beginning of generated code by <?php echo $form ?> --> 
     144        <tr> 
     145          <th><label for="name">Name</label></th> 
     146          <td><input type="text" name="name" id="name" /></td> 
     147        </tr> 
     148        <tr> 
     149          <th><label for="email">Email</label></th> 
     150          <td><input type="text" name="email" id="email" /></td> 
     151        </tr> 
     152        <tr> 
     153          <th><label for="message">Message</label></th> 
     154          <td><textarea rows="4" cols="30" name="message" id="message"></textarea></td> 
     155        </tr> 
     156        <!-- End of generated code by <?php echo $form ?> --> 
     157 
     158        <tr> 
     159          <td colspan="2"> 
     160            <input type="submit" /> 
     161          </td> 
     162        </tr> 
     163      </table> 
     164    </form> 
     165         
     166Widzimy, że formularz jest wyświetlany z trzema liniami `<tr>` tabeli HTML. Dlatego trzeba było umieścić go w tagu `<table>`. Każda linia zawiera tag `<label>` oraz tagi formularza (`<input>` lub `<textarea>`). 
     167 
     168### Etykiety 
     169 
     170Etykiety każdego pola są generowane automatycznie. Domyślnie etykiety są transformacją nazwy pola zgodnie z obowiązującymi zasadami: pierwsza litera duża i podkreślenia zastępuje spację. 
     171Przykład: 
     172 
     173 
     174    [php] 
     175    $this->setWidgets(array( 
     176      'first_name' => new sfWidgetFormInput(), // wygenerowana etykieta: "First name" 
     177      'last_name'  => new sfWidgetFormInput(), // wygenerowana etykieta: "Last name" 
     178    )); 
     179     
     180Nawet jeśli automatyczne generowanie etykiet jest bardzo przydatne, framework pozwala na zdefiniowanie spersonalizowanych etykiet za pomocą metody `setLabels()` : 
     181 
     182    [php] 
     183    $this->widgetSchema->setLabels(array( 
     184      'name'    => 'Your name', 
     185      'email'   => 'Your email address', 
     186      'message' => 'Your message', 
     187    )); 
     188 
     189Możesz również zmodyfikować pojedynczą etykietę przy użyciu metody `setLabel()`: 
     190 
     191    [php] 
     192    $this->widgetSchema->setLabel('email', 'Your email address'); 
     193 
     194Na koniec zobaczymy w Rozdziale trzecim, że można rozszerzyć etykiety z template w celu dalszego dostosowania formularza. 
     195 
     196>**Sidebar** 
     197>Schemat widżetów 
     198> 
     199>Kiedy używamy metody `setWidgets()`, Symfony tworzy obiekt `sfWidgetFormSchema`. Ten obiekt jest widżetem, który pozwala reprezentować zestaw widżetów. W naszym formularzu `ContactForm`, wywołaliśmy metodę `setWidgets()`. Jest to odpowiednik następującego kodu: 
     200> 
     201>     [php] 
     202>     $this->setWidgetSchema(new sfWidgetFormSchema(array( 
     203>       'name'    => new sfWidgetFormInput(), 
     204>       'email'   => new sfWidgetFormInput(), 
     205>       'message' => new sfWidgetFormTextarea(), 
     206>     ))); 
     207> 
     208>     // almost equivalent to : 
     209> 
     210>     $this->widgetSchema = new sfWidgetFormSchema(array( 
     211>       'name'    => new sfWidgetFormInput(), 
     212>       'email'   => new sfWidgetFormInput(), 
     213>       'message' => new sfWidgetFormTextarea(), 
     214>     )); 
     215> 
     216>Metoda `setLabels()` jest stosowana w kolekcji widżetów zawartych w obiekcie `widgetSchema`. 
     217> 
     218> Zobaczymy w Rozdziale 5, że notacja "schema widget" ułatwia zarządzanie wbudowanymi formularzami. 
     219 
     220### Poza wygenerowanymi tabelami 
     221 
     222Nawet jeśli formularz tabeli wyświetla domyślnie format tabeli w HTML, to layout może ulec zmianie. Te różne rodzaje formatów layout'u są zdefiniowane w klasach dziedziczących z `sfWidgetFormSchemaFormatter`. Domyślnie formularz używa formatu `table` tak jak jest zdefiniowane w klasie `sfWidgetFormSchemaFormatterTable`. Możesz też użyć formatu `list`: 
     223 
     224    [php] 
     225    class ContactForm extends sfForm 
     226    { 
     227      public function configure() 
     228      { 
     229        $this->setWidgets(array( 
     230          'name'    => new sfWidgetFormInput(), 
     231          'email'   => new sfWidgetFormInput(), 
     232          'message' => new sfWidgetFormTextarea(), 
     233        )); 
     234 
     235        $this->widgetSchema->setFormFormatterName('list'); 
     236      } 
     237    } 
     238 
     239Te dwa formaty są domyślne, a w rozdziale 5 będziesz mógł zobaczyć, w jaki sposób tworzyć własne klasy formatów. Teraz, gdy wiemy, w jaki sposób wyświetlić formularz, zobaczmy jak przesłać formularz. 
     240 
     241### Przesyłanie formularzy 
     242Kiedy tworzyliśmy template do wyświetlania formularza, użyliśmy wewnętrznych URL `contact/submit` w tagu formularza aby wysłać formularz. Teraz musimy dodać akcją `submit` w module `contact`. Listing 1-5 pokazuje, jak akcja może otrzymać informacje od użytkowników i przekierować do strony `thank you`, na której wyświetlona zostanie informacja zwrotna dla użytkownika. 
     243 
     244Listing 1-5 - Użycie akcji `submit` w module `contact` 
     245 
     246    [php] 
     247    public function executeSubmit($request) 
     248    { 
     249      $this->forward404Unless($request->isMethod('post')); 
     250 
     251      $params = array( 
     252        'name'    => $request->getParameter('name'), 
     253        'email'   => $request->getParameter('email'), 
     254        'message' => $request->getParameter('message'), 
     255      ); 
     256 
     257      $this->redirect('contact/thankyou?'.http_build_query($params)); 
     258    } 
     259 
     260    public function executeThankyou() 
     261    { 
     262    } 
     263 
     264    // apps/frontend/modules/contact/templates/thankyouSuccess.php 
     265    <ul> 
     266      <li>Name:    <?php echo $sf_params->get('name') ?></li> 
     267      <li>Email:   <?php echo $sf_params->get('email') ?></li> 
     268      <li>Message: <?php echo $sf_params->get('message') ?></li> 
     269    </ul> 
     270 
     271 
     272>**Note** 
     273>`http_build_query` jest wbudowaną funkcja PHP, która generuje URL-encoded ciąg znaków z tablicy parametrów. 
     274 
     275metoda `executeSubmit()` realizuje trzy akcje: 
     276 
     277* Ze względów bezpieczeństwa sprawdzamy, czy strona została przesłana za pomocą HTTP metody `POST`. Jeśli nie jest przesyłana za pomocą metody `POST`, użytkownik zostaje przekierowany na stronę 404. W template `indexSuccess`, zadeklarowaliśmy metodę jako `POST` (`<form ... method="POST">`): 
     278 
     279        [php] 
     280        $this->forward404Unless($request->isMethod('post')); 
     281 
     282* Następnie otrzymujemy wartości z pól wypełnionych przez użytkownika, aby przechować je w tablicy `params`: 
     283 
     284        [php] 
     285        $params = array( 
     286          'name'    => $request->getParameter('name'), 
     287          'email'   => $request->getParameter('email'), 
     288          'message' => $request->getParameter('message'), 
     289        ); 
     290 
     291* Na koniec, przekierowujemy użytkownika do strony Thank you (`contact/thankyou`), aby wyświetlić jego informacje: 
     292 
     293        [php] 
     294        $this->redirect('contact/thankyou?'.http_build_query($params)); 
     295 
     296 
     297Zamiast przekierowywać użytkownika do innej strony, możemy stworzyć template `submitSuccess.php`. O ile to możliwe, lepszą praktyką jest zawsze przekierować użytkownika po żądaniu metodą `POST`: 
     298 
     299* To zapobiega przed powtórnym zatwierdzeniem formularza, jeżeli użytkownik przeładuje stronę  Thank you. 
     300 
     301* Użytkownik może również kliknąć na przycisku "Wstecz", bez uzyskiwania pop-up, aby wysłać formularz ponownie. 
     302 
     303>**Tip** 
     304>Z pewnością zauważyłeś, że `executeSubmit()` różni się od `executeIndex()`. Podczas wywoływania tych metod symfony przenosi bieżący obiekt `sfRequest` jako pierwszy argument do metod  `executeXXX()`. W PHP, nie musisz zbierać wszystkich parametrów, dlatego nie zdefiniowaliśmy zmiennej `request` w `executeIndex()` ponieważ nie potrzebowaliśmy tego. 
     305 
     306Rysunek 1-5 pokazuje, metodę działania podczas interakcji z użytkownikiem. 
     307 
     308Figure 1-5 - Metody działania 
     309 
     310![Methods workflow](/images/forms_book/en/01_05.png "Methods workflow") 
     311 
     312>**Note** 
     313> Podczas ponownego wyświetlenia pola użytkownika w template, ryzykujemy atak XSS (Cross-Site Scripting). Możesz znaleźć więcej informacji na temat sposobów uniknięcia ryzyka XSS poprzez wdrożenie strategii ucieczki w Rozdziale [Inside the View Layer](http://www.symfony-project.org/book/1_2/07-Inside-the-View-Layer#chapter_07_output_escaping) książki "The Definitive Guide to symfony". 
     314 
     315Po wysłaniu formularza powinieneś teraz zobaczyć stronę z Rysunku 1-6. 
     316 
     317Figure 1-6 - Strona wyświetlona po przesłaniu formularza 
     318 
     319![Page displayed after submitting the form](/images/forms_book/en/01_06.png "Page displayed after submitting the form") 
     320 
     321Zamiast tworzyć tablicę `params`, łatwiej będzie uzyskać informacje od użytkownika bezpośrednio w tablicy. Listing 1-6 modyfikuje atrybut HTML `name` z widżetów, tak aby przechowywać wartości z pól w tablicy `contact`. 
     322 
     323Listing 1-6 - Modyfikacja atrybutu HTML `name` z widżetów 
     324 
     325    [php] 
     326    class ContactForm extends sfForm 
     327    { 
     328      public function configure() 
     329      { 
     330        $this->setWidgets(array( 
     331          'name'    => new sfWidgetFormInput(), 
     332          'email'   => new sfWidgetFormInput(), 
     333          'message' => new sfWidgetFormTextarea(), 
     334        )); 
     335 
     336        $this->widgetSchema->setNameFormat('contact[%s]'); 
     337      } 
     338    } 
     339 
     340 
     341Wywołanie `setNameFormat()`, pozwala nam zmodyfikować atrybut HTML `name` dla wszystkich widżetów. `%s` zostanie automatycznie zastąpiony przez nazwę pola, podczas generowania formularza. Na przykład, atrybut `name` zostanie zmieniony `contact[email]` dla pola `email`. PHP automatycznie tworzy tablicę z wartościami żądania zawierając format `contact[email]`. W ten sposób wartości pól będą dostępne w tablicy `contact`. 
     342 
     343Teraz możemy bezpośrednio otrzymać tablicę `contact` z obiektu `request`, jak pokazano na Listingu 1-7. 
     344 
     345Listing 1-7 - Nowy format atrybutu `name` w akcji widżetów 
     346   
     347    [php] 
     348    public function executeSubmit($request) 
     349    { 
     350      $this->forward404Unless($request->isMethod('post')); 
     351 
     352      $this->redirect('contact/thankyou?'.http_build_query($request->getParameter('contact'))); 
     353    } 
     354 
     355Podczas wyświetlania źródła HTML formularza, możesz dostrzec, że symfony wygenerowało atrybut `name` zależny nie tylko od nazwy pola i formatu, ale także od atrybutu `id`. Atrybut `Id` jest tworzony automatycznie z atrybutu `name` poprzez umieszczenie podkreślenia (`_`): 
     356 
     357<table cellspacing="0"> 
     358<thead> 
     359<tr> 
     360  <th>Nazwa</th> 
     361  <th>Atrybut name </th> 
     362  <th>Atrybut id </th> 
     363</tr> 
     364</thead> 
     365 
     366<tbody> 
     367<tr> 
     368  <td>name</td> 
     369  <td>contact[name]</td> 
     370  <td>contact_name</td> 
     371</tr> 
     372<tr> 
     373  <td>email</td> 
     374  <td>contact[email]</td> 
     375 
     376  <td>contact_email</td> 
     377</tr> 
     378<tr> 
     379  <td>message</td> 
     380  <td>contact[message]</td> 
     381  <td>contact_message</td> 
     382</tr> 
     383</tbody> 
     384</table> 
     385 
     386 
     387### Inne rozwiązanie 
     388 
     389W tym przykładzie użyliśmy dwóch akcji do zarządzania formularzem: `index` do wyświetlania, `submit` w celu przesłania. Ze względu na to, że formularz wyświetlany przy pomocy `GET` i przesłany metodą `POST`, możemy połączyć dwie metody w jedną `index`, jak pokazano na Listingu 1-8. 
     390 
     391Listing 1-8 - Merging of the two actions used in the form 
     392 
     393    [php] 
     394    class contactActions extends sfActions 
     395    { 
     396      public function executeIndex($request) 
     397      { 
     398        $this->form = new ContactForm(); 
     399 
     400        if ($request->isMethod('post')) 
     401        { 
     402          $this->redirect('contact/thankyou?'.http_build_query($request->getParameter('contact'))); 
     403        } 
     404      } 
     405    } 
     406 
     407Potrzebujesz również zmienić atrybut w `action` formularza w template `indexSuccess.php`: 
     408 
     409    [php] 
     410    <form action="<?php echo url_for('contact/index') ?>" method="POST"> 
     411 
     412Jak zobaczymy później, wolimy używać tej składni, ponieważ jest krótsza i czyni kod bardziej spójnym i zrozumiałym. 
     413 
     414 
     415Konfiguracja Widżetów 
     416----------------------- 
     417 
     418### Opcje widżetów 
     419 
     420         
     421Jeśli strona jest zarządzana przez wielu webmasterów, to my na pewno chcemy dodać rozwijaną listę tematów w celu przekierowania wiadomości zgodnie z tym co jest wybrane (rys. 1-7). Listing 1-9 dodaje `subject` z listą rozwijaną przy użyciu widżetu `sfWidgetFormSelect`. 
     422 
     423Rysunek 1-7 - Dodanie pola `subject` do formularza 
     424 
     425![Adding a `subject` Field to the Form](/images/forms_book/en/01_07.png "Adding a `subject` Field to the Form") 
     426 
     427Listing 1-9 - Dodanie pola `subject` do formularza 
     428 
     429    [php] 
     430    class ContactForm extends sfForm 
     431    { 
     432      protected static $subjects = array('Subject A', 'Subject B', 'Subject C'); 
     433 
     434      public function configure() 
     435      { 
     436        $this->setWidgets(array( 
     437          'name'    => new sfWidgetFormInput(), 
     438          'email'   => new sfWidgetFormInput(), 
     439          'subject' => new sfWidgetFormSelect(array('choices' => self::$subjects)), 
     440          'message' => new sfWidgetFormTextarea(), 
     441        )); 
     442 
     443        $this->widgetSchema->setNameFormat('contact[%s]'); 
     444      } 
     445    } 
     446 
     447 
     448>**SIDEBAR** 
     449> Opcja `choices` widżetu `sfWidgetFormSelect` 
     450> 
     451> W PHP nie ma żadnej różnicy między tablicą i tablicą asocjacyjną, więc tablica, którą użyliśmy jako listy jest identyczna z następującym kodem: 
     452> 
     453>     [php] 
     454>     $subjects = array(0 => 'Subject A', 1 => 'Subject B', 2 => 'Subject C'); 
     455> 
     456> Wygenerowany widget bierze klucze tablicy jako atrybut `value` tagu `option` tag i powiązana wartość jako zawartość tagu: 
     457> 
     458>     [php] 
     459>     <select name="contact[subject]" id="contact_subject"> 
     460>       <option value="0">Subject A</option> 
     461>       <option value="1">Subject B</option> 
     462>       <option value="2">Subject C</option> 
     463>     </select> 
     464> 
     465> Aby zmienić atrybuty `value`, po prostu musimy zdefiniować klucze tablicy: 
     466> 
     467>     [php] 
     468>     $subjects = array('A' => 'Subject A', 'B' => 'Subject B', 'C' => 'Subject C'); 
     469> 
     470>Który generuje template w HTML: 
     471> 
     472>     [php] 
     473>     <select name="contact[subject]" id="contact_subject"> 
     474>       <option value="A">Subject A</option> 
     475>       <option value="B">Subject B</option> 
     476>       <option value="C">Subject C</option> 
     477>     </select> 
     478         
     479Widget `sfWidgetFormSelect`, tak jak wszystkie widżety, posiada listę opcji jako pierwszy argument. Opcja ta może być obowiązkowa lub nieobowiązkowa. Widget `sfWidgetFormSelect` ma obowiązkową opcję `choices`. Oto dostępne opcje widżetów użytych do tej pory: 
     480   
     481<table cellspacing="0"> 
     482<thead> 
     483<tr> 
     484  <th>Widżet</th> 
     485  <th>Opcje obowiązkowe</th> 
     486  <th>Opcje nieobowiązkowe</th> 
     487</tr> 
     488</thead> 
     489<tbody> 
     490<tr> 
     491  <td><code>sfWidgetFormInput</code></td> 
     492  <td>-</td> 
     493  <td><code>type</code> (default to <code>text</code>)</td> 
     494</tr> 
     495<tr> 
     496  <td></td> 
     497  <td></td> 
     498  <td><code>is_hidden</code> (default to <code>false</code>)</td> 
     499</tr> 
     500<tr> 
     501  <td><code>sfWidgetFormSelect</code></td> 
     502  <td><code>choices</code></td> 
     503  <td><code>multiple</code> (default to <code>false</code>)</td> 
     504</tr> 
     505<tr> 
     506  <td><code>sfWidgetFormTextarea</code></td> 
     507  <td>-</td> 
     508  <td>-</td> 
     509</tr> 
     510</tbody> 
     511</table> 
     512 
     513>**Tip** 
     514         
     515> Jeśli chcesz znać wszystkie opcje widżetów możesz zapoznać się z pełną dokumentację API dostępną na stronie internetowej ([http://www.symfony-project.org/api/1_2/](http://www.symfony-project.org/api/1_2/)). Wszystkie opcje są wyjaśnione, zarówno dodatkowe jak i domyślne. Na przykład, wszystkie opcje `sfWidgetFormSelect` dostępne są tutaj: ([http://www.symfony-project.org/api/1_2/sfWidgetFormSelect](http://www.symfony-project.org/api/1_2/sfWidgetFormSelect)). 
     516 
     517 
     518### Atrybuty HTML widżetów 
     519 
     520Każdy widget pobiera listę atrybutów HTML jako drugi opcjonalny argument. Jest to bardzo pomocne do określenia domyślnych atrybutów HTML dla wygenerowanych tagów formularza. Listing 1-10 pokazuje jak dodać atrybut `class` do pola `email`. 
     521 
     522Listing 1-10 - Definiowanie atrybutów do widgetu 
     523 
     524    [php] 
     525    $emailWidget = new sfWidgetFormInput(array(), array('class' => 'email')); 
     526 
     527    // Generated HTML 
     528    <input type="text" name="contact[email]" class="email" id="contact_email" /> 
     529 
     530Atrybuty HTML także pozwalają nam zastąpić automatycznie wygenerowany identyfikator, jak pokazano na listingu 1-11. 
     531 
     532Listing 1-11 - Nadpisywanie atrybutu `id` 
     533 
     534    [php] 
     535    $emailWidget = new sfWidgetFormInput(array(), array('class' => 'email', 'id' => 'email')); 
     536 
     537    // Generated HTML 
     538    <input type="text" name="contact[email]" class="email" id="email" /> 
     539 
     540Jest możliwość ustawienia domyślnych wartości pól za pomocą atrybutu `value`, pokazuje to Listing 1-12. 
     541 
     542Listing 1-12 - Domyślne wartości widżetów za pomocą atrybutów HTML 
     543 
     544    [php] 
     545    $emailWidget = new sfWidgetFormInput(array(), array('value' => 'Your Email Here')); 
     546 
     547    // Generated HTML 
     548    <input type="text" name="contact[email]" value="Your Email Here" id="contact_email" /> 
     549 
     550Ta opcja działa dla widżetów `input`, trudno jest użyć dla widżetów `checkbox` lub `radio`, a nawet niemożliwe w widżecie `textarea`. Klasa `SfForm` oferuje konkretne metody w celu określenia wartości domyślnych dla każdego pola w jednolity sposób dla każdego typu widżetów. 
     551 
     552>**Note** 
     553>Polecamy określenie atrybutów HTML wewnątrz template, a nie w samym formularzu (nawet jeśli jest to możliwe), aby zachować warstwy separacji tak jak to zobaczymy w rozdziale trzy. 
     554 
     555### Definiowanie wartości domyślnych pól 
     556 
     557Często przydatne jest określenie wartości domyślnej dla każdego pola. Na przykład, gdy wyświetlamy komunikat pomocy pola, który znika, gdy użytkownik klika na polu. Listing 1-13 pokazuje jak zdefiniować wartości domyślne za pomocą metod `setDefault()` i `setDefaults()`. 
     558 
     559Listing 1-13 - Wartości domyślne widżetów poprzez metody `setDefault()` i `setDefaults()` 
     560 
     561    [php] 
     562    class ContactForm extends sfForm 
     563    { 
     564      public function configure() 
     565      { 
     566        // ... 
     567 
     568        $this->setDefault('email', 'Your Email Here'); 
     569 
     570        $this->setDefaults(array('email' => 'Your Email Here', 'name' => 'Your Name Here')); 
     571      } 
     572    } 
     573 
     574Metody `SetDefault()` i `setDefaults()` są bardzo pomocne do określenia 
     575identycznych wartości domyślnych dla każdej instancji tej samej klasy formularza. Jeśli chcemy  
     576zmodyfikować istniejący obiekt przy użyciu formularza, wartości domyślne 
     577zależą od instancji, w związku z tym muszą być dynamiczne. Listing 1-14 pokazuje 
     578konstruktor `sfForm`, którego pierwszy argument ustawia wartości domyślne 
     579dynamicznie. 
     580 
     581Listing 1-14 - Wartości domyślne widżetów poprzez konstruktor `sfForm` 
     582 
     583    [php] 
     584    public function executeIndex($request) 
     585    { 
     586      $this->form = new ContactForm(array('email' => 'Your Email Here', 'name' => 'Your Name Here')); 
     587 
     588      // ... 
     589    } 
     590 
     591>**SIDEBAR** 
     592>Zabezpieczenia XSS (Cross-Site Scripting) 
     593>        
     594>Przy określaniu atrybutów HTML dla widżetów lub określaniu wartości domyślnych, klasa `sfForm` automatycznie chroni te wartości przed atakami XSS podczas generowania kodu HTML. Ochrona ta nie zależy od konfiguracji `escaping_strategy` w plku `settings.yml`. Jeśli zawartość jest już chroniona w inny sposób, ochrona nie będzie zastosowana ponownie. 
     595 
     596> To chroni również `'` i `"` znaki, które mogłyby naruszyć wygenerowany kod HTML. 
     597> 
     598> Oto przykład tej ochrony: 
     599> 
     600>     [php] 
     601>     $emailWidget = new sfWidgetFormInput(array(), array( 
     602>       'value' => 'Hello "World!"', 
     603>       'class' => '<script>alert("foo")</script>', 
     604>     )); 
     605>      
     606>     // Generated HTML 
     607>     <input 
     608>       value="Hello &quot;World!&quot;" 
     609>       class="&lt;script&gt;alert(&quot;foo&quot;)&lt;/script&gt;" 
     610>       type="text" name="contact[email]" id="contact_email" 
     611>     /> 
     612 
     613 
     614[Markdown text here] 
     615 
     616}}}