Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZF][ZendFramework] Pole select waliduje się niepoprawnie
Forum PHP.pl > Forum > PHP > Frameworki
Vill
Mam pole select, które zawiera wartość nullową i kilku klientów do wyboru. Walidacja przechodzi poprawnie tylko w przypadku wyboru wartości null, w przypadku wyboru jakiegoś klienta to nie przechodzi. Nie mam ustawionych na tym polu żadnych walidatorów ani filtrów.

Polę buduję w ten sposób:

Tworzę pole w klasie dziedziczącej po Zend_Form budującej formularz
  1. $client_login = $this->createElement('select', 'client', array('label' => 'Wybierz klienta:'));


Potem uzupełniam w odpowiednim kontrolerze pobierającym wcześniej dane z bazy (formularz w zmiennej $this->createForm)
  1. $stmt = $this->db->query($select);
  2. $result = $stmt->fetchAll();
  3.  
  4. $clientSelect = $this->createForm->getElement('client');
  5.  
  6. $clientSelect->addMultiOption(null, 'Brak klienta');
  7.  
  8. foreach($result as $c) {
  9. $clientSelect->addMultiOption($c['ClientLogin'], $c['ClientLogin']);
  10. }


No i przekazuję formularz do widoku.

Gdzie może leżeć błąd? Dlaczego walidacja nie przepuszcza wszystkich wartości?
Turson
Zobacz jak wygląda rzeczywiście select poprzez "Zbadaj element"
Vill
  1. <select name="client" id="client">
  2. <option value="">Brak klienta</option>
  3. <option value="Mort">Mort</option>
  4. <option value="Julian">Julian</option>


Wartości są przekazywane postem poprawnie.
Lysiur
Wyglada na to, że po wysłaniu formularza, nie jest on prawidłowo zbudowany. Fragment z foreachem się nie wykonuje. Pokaż może jak wygląda fragment controllera gdzie budujesz formularz i validujesz requesta
Vill
Klasa z formularzem

  1. class Application_Form_CreateEvent extends Zend_Form {
  2.  
  3. public function init() {
  4.  
  5. $this->setMethod('post');
  6.  
  7. $this->setAttrib('id', 'create-event-form');
  8. $this->setAttrib('class', 'form');
  9.  
  10. //elementy
  11. $client_login = $this->createElement('select', 'client', array('label' => 'Wybierz klienta:'));
  12. $title = $this->createElement('text', 'title', array('label' => 'Tytuł:'));
  13. $desc = $this->createElement('textarea', 'desc', array('label' => 'Opis:'));
  14. $date = $this->createElement('text', 'date', array('label' => 'Data:'));
  15. $time = $this->createElement('text', 'time', array('label' => 'Godzina:'));
  16.  
  17. $login_input = $this->createElement('hidden', 'login_input');
  18. $submit = $this->createElement('submit', 'submit', array('value' => 'Wyślij'));
  19.  
  20. //walidatory i filtry
  21. $title->addValidator('stringLength', false, array(2, 255));
  22. ....
  23.  
  24. //złożenie formularza
  25. $this->addElement($client_login)
  26. ->addElement($title)
  27. ->addElement($date)
  28. ->addElement($time)
  29. ->addElement($desc)
  30. ->addElement($login_input)
  31. ->addElement($submit)
  32. ->addElement('hash', 'csrf', array('ignore' => true));
  33. }
  34. }


Akcja kontrolera uzupełniająca ten formularz o dodatkowe dane:
  1.  
  2. public function createAction() {
  3.  
  4. //ACL
  5. $hasAccess = $this->_helper->aclHelper($this->_request->getControllerName(), $this->getRequest()->getActionName());
  6.  
  7. if(!$hasAccess['access']){
  8. $this->view->message = $this->_helper->messageHelper('FORBIDDEN','RED');
  9. $this->view->redirectPath = '/trainer/login';
  10. return;
  11. }
  12.  
  13. //login trenera
  14. $login = $hasAccess['login'];
  15.  
  16. $this->createForm->setAction('/individevent/createform');
  17.  
  18. //uzupełnienie formularza o login trenera
  19. $loginInput = $this->createForm->getElement('login_input');
  20. $loginInput->setValue($login);
  21.  
  22. //uzupełnienie pola select o klientów
  23. $select = $this->db->select()
  24. ->from('trainer_client', 'ClientLogin')
  25. ->where('TrainerLogin = ?', $login);
  26.  
  27. $stmt = $this->db->query($select);
  28. $result = $stmt->fetchAll();
  29.  
  30. $clientSelect = $this->createForm->getElement('client');
  31.  
  32. $clientSelect->addMultiOption(null, 'Brak klienta');
  33. foreach($result as $c) {
  34. $clientSelect->addMultiOption($c['ClientLogin'], $c['ClientLogin']);
  35. }
  36.  
  37. //przekazanie formularza do widoku
  38. $this->view->createForm = $this->createForm;
  39. }


Akcja kontrolera przetwarzająca dane z formularza:

  1. public function createformAction() {
  2.  
  3. //sprawdzenie, czy nastąpiło przesłanie danych
  4. if(!$this->_request->isPost()) {
  5. $this->view->message = $this->_helper->messageHelper('POSTFAIL','RED');
  6. $this->view->redirectPath = '/';
  7. return;
  8. }
  9.  
  10. //walidacja
  11. if (!$this->createForm->isValid($this->_request->getPost())) {
  12. echo 'client: '.$this->_request->getPost('client').'</br>'; //wypisuje się prawidłowo wybrany klient
  13. $this->view->message = $this->_helper->messageHelper('VALIDATIONFAIL','RED');
  14. $this->view->redirectPath = '/';
  15. return;
  16. }
  17.  
  18. //przedworzenie danych
  19. //.......
  20.  
  21. }
Lysiur
Okej, co prawda nie jak wiem co dokładnie siedzi w zmiennej $this->createForm, ale zakładam, że w controllerze ( w init) tworzysz formularz i go wkładasz do $this->createForm.

Twój problem z formularzem na tym, że w metodzie createAction() uzupełniasz opcje związane nowymi pozycjami (select). Natomiast po wysłaniu requesta, do metody createformAction(), formularz jest czysty (to nie ten sam obiekt co zbudowany w createAction()) i nie posiada dodatkowych pozycji w selekcie. W akcji przetwarzającej ten formularz także musisz go uzupełnić (przed walidacją) o możliwe do wyboru pozycjie inaczej formularz będzie krzyczał, że nie ma opcji.

Zrób sobie mniejwięcej coś takiego:


  1. //Formularz
  2. class Application_Form_CreateEvent extends Zend_Form {
  3. public function init() {
  4. //......
  5. }
  6.  
  7. public function setClientsOption(array $clients) {
  8. $this->getElement('client')->setMultioptions($clients);
  9. }
  10.  
  11. }
  12.  
  13. //Controller
  14. class SomeController {
  15.  
  16. private function getForm() {
  17.  
  18. $clients = array(); //Lista klientów do wyświetlenia
  19.  
  20. $form = new Application_Form_CreateEvent();
  21. $form->setClientsOption($clients);
  22. return $form;
  23. }
  24.  
  25. public function createAction() {
  26. $form = $this->getForm();
  27. //....
  28. $this->view->form = $form;
  29. }
  30.  
  31. public function createformAction() {
  32. $form = $this->getForm();
  33.  
  34. if($form->isValid()) {
  35. //...
  36. }
  37.  
  38. }
  39.  
  40. }


Generalnie chodzi o to, byś formularz (już ze wszsytkimi opcjami) pobierał w jednolity sposób do akcji wyświetlania i zapisu.
Vill
Faktycznie masz rację. Ale to dziwne, ponieważ wszystkie wartości, które wpisuję w ukryte inputy są widoczne w każdej akcji (jeśli ją podepnę do action formularza). Testowałam też na polach 'text' i także ich wartości są widoczne w każdej akcji. Tylko select coś się resetuje. Ale pokombinuję jeszcze i może coś mi się uda z tym zrobić.

Dzięki!
Lysiur
Dzieje się tak ponieważ 'wartości' są przekazywane do formularza z requesta, poprzez metodę $form->isValid(requrest), natomiast same opcje poszczególnych pól należą do obiektu Form i nie są one przekazywane z requestem.
Vill
No tak, wiem, tylko myślałam że na wartości walidowane po submicie nie wpływa struktura pola, że sama wartość wybranej opcji jest brana pod uwagę podczas walidacji. A wartości przychodzą dobre.
Zrobiłam teraz tak, że waliduje to pole osobno klasycznym czysto phpowym sposobem, potem je usuwam i na formularzu z usuniętym polem wywołuje isValid() żeby walidowała się cała reszta. Może i trochę nachalne rozwiązanie ale szybkie i niezbyt kłopotliwe. Jak zostanie czasu to wykombinuję coś ładniejszego smile.gif.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.