Development

Documentation/pl_PL/forms (diff)

You must first sign up to be able to contribute.

Changes between Version 1 and Version 2 of Documentation/pl_PL/forms

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

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/pl_PL/forms

    v1 v2  
    1 {{{ 
    2 #!WikiMarkdown 
    3  
    4 Rozdział 1 - tworzenie formularzy 
    5 ========================= 
    6  
    7 Formularz 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  
    9 Symfony 1.1 wymaga zastosowania się do rozdziałów tej książki. Będziesz również potrzebował stworzyć projekt i `frontend` projektu.  
    10 W celu uzyskania więcej informacji na temat tworzenia projektu symfony proszę odnieść się do dokumentacji głównej. 
    11  
    12 Zanim zaczniemy 
    13 --------------- 
    14  
    15 Zaczniemy dodając formularz kontaktowy do aplikacji symfony. 
    16  
    17 Rysunek 1-1 pokazuje formularz kontaktowy z punktu widzenia użytkowników, którzy chcą wysłać wiadomość. 
    18  
    19 Rysunek 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  
    24 Stworzymy 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  
    26 Rysunek 1-2 - Strona z podziękowaniem 
    27  
    28 ![Thank you page](/images/forms_book/en/01_02.png "Thank you page") 
    29  
    30 Rysunek 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  
    35 Widżety 
    36 ------- 
    37  
    38 ### Klasy `SfForm` i `sfWidget`  
    39  
    40 Uż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  
    45 Moż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ść`.  
    48 Listing 1-1 przedstawia pierwszą implementację klasy `ContactForm`. 
    49  
    50 Listing 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  
    73 Widżety są zdefiniowane w metodzie `configure()`. Metoda ta jest wywoływana automatycznie przez konstruktora klasy `sfForm`. 
    74  
    75 Metoda `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  
    85 Nasz 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      
    90 W module `contact`, zmieńmy akcję `index` tak aby przejść do template'ki formularza tak jak pokazano na Listingu 1-2. 
    91  
    92 Listing 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      
    104 Przy tworzeniu formularza, metoda `configure()`, zdefiniowana wcześniej, będzie wywoływana automatycznie. 
    105  
    106 My po prostu musimy teraz stworzyć template, aby wyświetlić formularz w sposób pokazany na listingu 1-3. 
    107  
    108 Listing 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  
    124 Formularz 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  
    126 Korzystanie 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** 
    129 Podczas 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  
    131 Możemy teraz zobaczyć formularz w przeglądarce (rys. 1-4) i sprawdzić wynik, wywołując akcję `contact/index` (`/frontend_dev.php/contact`). 
    132  
    133 Rysunek 1-4 - Wygenerowany formularz kontaktowy 
    134  
    135 ![Generated Contact Form](/images/forms_book/en/01_04.png "Generated Contact Form") 
    136  
    137 Listing 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          
    166 Widzimy, ż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  
    170 Etykiety 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ę. 
    171 Przykł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      
    180 Nawet 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  
    189 Możesz również zmodyfikować pojedynczą etykietę przy użyciu metody `setLabel()`: 
    190  
    191     [php] 
    192     $this->widgetSchema->setLabel('email', 'Your email address'); 
    193  
    194 Na 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  
    222 Nawet 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  
    239 Te 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 
    242 Kiedy 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  
    244 Listing 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  
    275 metoda `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  
    297 Zamiast 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  
    306 Rysunek 1-5 pokazuje, metodę działania podczas interakcji z użytkownikiem. 
    307  
    308 Figure 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  
    315 Po wysłaniu formularza powinieneś teraz zobaczyć stronę z Rysunku 1-6. 
    316  
    317 Figure 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  
    321 Zamiast 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  
    323 Listing 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  
    341 Wywoł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  
    343 Teraz możemy bezpośrednio otrzymać tablicę `contact` z obiektu `request`, jak pokazano na Listingu 1-7. 
    344  
    345 Listing 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  
    355 Podczas 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  
    389 W 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  
    391 Listing 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  
    407 Potrzebujesz 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  
    412 Jak zobaczymy później, wolimy używać tej składni, ponieważ jest krótsza i czyni kod bardziej spójnym i zrozumiałym. 
    413  
    414  
    415 Konfiguracja Widżetów 
    416 ----------------------- 
    417  
    418 ### Opcje widżetów 
    419  
    420          
    421 Jeś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  
    423 Rysunek 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  
    427 Listing 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          
    479 Widget `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  
    520 Każ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  
    522 Listing 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  
    530 Atrybuty HTML także pozwalają nam zastąpić automatycznie wygenerowany identyfikator, jak pokazano na listingu 1-11. 
    531  
    532 Listing 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  
    540 Jest możliwość ustawienia domyślnych wartości pól za pomocą atrybutu `value`, pokazuje to Listing 1-12. 
    541  
    542 Listing 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  
    550 Ta 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  
    557 Czę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  
    559 Listing 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  
    574 Metody `SetDefault()` i `setDefaults()` są bardzo pomocne do określenia 
    575 identycznych wartości domyślnych dla każdej instancji tej samej klasy formularza. Jeśli chcemy  
    576 zmodyfikować istniejący obiekt przy użyciu formularza, wartości domyślne 
    577 zależą od instancji, w związku z tym muszą być dynamiczne. Listing 1-14 pokazuje 
    578 konstruktor `sfForm`, którego pierwszy argument ustawia wartości domyślne 
    579 dynamicznie. 
    580  
    581 Listing 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 }}}