Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony] Problem z sfValidatorPropelUnique
Forum PHP.pl > Forum > PHP > Frameworki
blackroger
Witam. Mam problem dotyczący sfValidatorPropelUnique. Wszystko działa jak należy przy rejestracji tylko chcę go wykorzystać do zmiany danych użytkownika. Problem pojawia w momencie próby zmiany powiedzmy loginu który jest unikalny.
  1. $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
  2. new sfValidatorPropelUnique(
  3. array('model'=>'Uzytkownicy',
  4. 'column'=>'login'),
  5. array('invalid'=>'Podany login już istnieje'))
  6. ..........
  7. ....
  8. ...
  9. )));


Jak zrobić żeby ten walidator szukał unikalności tylko i wyłącznie dla wszystkich loginów różnych od loginu który jest aktualnie używany przez tego użytkownika. Powiedzmy że login jest Jasiu i użytkownik pozostawia przy zmianie login taki sam, to postwalidator poinformuje ze taki w bazie istnieje, a nie powinien. Natomiast jak użytkownik zmieni login z Jasiu na Janek, a taki login bedzie już przydzielony do innego id to ma poinformowac o zajętości. Wiem że można to zrobić poprzez bezpośrednie zapytania sqlowe i redukcją danego loginu ale chciałbym to zrobić za pomocą sfValidatorPropelUnique. CZy jest taka możliwość? A jeżeli nie ma to proszę o jak najlepsze rozwiązanie.
Pr0100
problem nie dotyczy walidatora tylko deklaracji formularza.

  1. $c = new Criteraia();
  2.  
  3. /* w criteraia szukasz swojego "Jasia" */
  4.  
  5. $user = UserPeer::doSelectOne($c);
  6. $form = UserForm( $user );
blackroger
Albo nie do końca rozumiem albo nieprecyzyjnie przedstawiłem problem. Ja pobieram id po atrybutach użytkownika. Następnie Criteriami wyciągam jego dane i za pomocą powiedzmy $u->setName(), $u->setImie() itd ustawiam wartości poszczególnych pól. Czyli w momencie wejścia na akcję edycja, w formularzu są już wszystkie widoczne dane użytkownika które można zmieniać. I teraz chodzi o unikalność np loginów. Dopuszczam zmianę loginu jeżeli takowy nie został zajęty. I do tego walidator służy - sprawdza mi czy nie ma takiego w bazie, ale w momencie jak nie zmienię loginu ten sam walidator sprawdzi czy login nie został już zajęty i wyjdzie mu że tak bo przecież użytkownik aktualnie go posiada. Jak to obejść?
Pr0100
Cytat
za pomocą powiedzmy $u->setName(), $u->setImie() itd ustawiam wartości poszczególnych pól


i w ten sposób Symfony myśli że chcesz stworzyć nowego usera o takim samych danych, gdyby nie error w login to byś dostałbyś pewnie identyczny błąd dotyczący kolumny id. To trochę tak jakbyś chciał zrobić coś w tym stylu:

  1. $user = new User();
  2. $user->setLogin( 'Adam' );
  3. $user->save();
  4.  
  5. $user_edit = new User();
  6. $user_edit->setLogin('Adam');
  7. $user_edit->setId( $user->getId() );
  8. $user_edit->save();


Bez sensu. Aby uzyskać edycje danych należy zrobić to co napisałem w poprzednim poście.

Cytat
Czyli w momencie wejścia na akcję edycja, w formularzu są już wszystkie widoczne dane użytkownika które można zmieniać


jeżeli dobrze rozumiem to przypisujesz dane w pliku UserForm? blink.gif pokaż kod źródłowy formularza i akcji bo coś mi się wydaje że tworzysz jakiś nowy standard pisania w Symfony winksmiley.jpg
destroyerr
Bez Twojego formularza zbyt wiele napisać nie mogę. Jedno jest pewne, jeśli w formularzu wyślesz wszystkie klucze główne (zazwyczaj będzie to tylko id) to walidator rozpozna, że obiekt znaleziony w bazie to jest ten sam który został wysłany formularzem. Czyli w Twoim przypadku, jeśli wyślesz formularzem id użytkownika, a on nie zmieni swojej nazwy, to nie wyrzuci błędu, bo będą te same id.
blackroger
  1. class ChangeDataForm extends sfForm {
  2.  
  3. public function configure() {
  4. $this->setWidgets(array('login'=>new sfWidgetFormInput(),
  5. 'stare_haslo'=>new sfWidgetFormInputPassword(),
  6. 'nowe_haslo'=>new sfWidgetFormInputPassword(),
  7. 'nowe_powtorz'=>new sfWidgetFormInputPassword(),
  8. 'imie'=>new sfWidgetFormInput(),
  9. 'nazwisko'=>new sfWidgetFormInput(),
  10. 'miasto'=>new sfWidgetFormInput(),
  11. 'mail'=>new sfWidgetFormInput(),
  12. ));
  13.  
  14. $this->widgetSchema->setLabels(array('login'=>'Login:',
  15. 'stare_haslo'=>'Stare hasło:',
  16. 'nowe_haslo'=>'Nowe hasło:',
  17. 'nowe_powtorz'=>'Powtórz nowe hasło:',
  18. 'imie'=>'Imię:',
  19. 'nazwisko'=>'Nazwisko:',
  20. 'miasto'=>'Miasto:',
  21. 'mail'=>'E-mail:'
  22. ));
  23.  
  24. $this->setValidators(array('login'=>new sfValidatorString(
  25. array('required'=>true,
  26. 'min_length'=>3),
  27. array('min_length'=>'Login powinien składać się z
  28. minimum 3 znaków',
  29. 'required'=>'To pole jest wymagane')),
  30.  
  31. 'stare_haslo'=>new sfValidatorString(
  32. array('required'=>true,
  33. 'min_length'=>6),
  34. array('min_length'=>'Hasło powinno składać się z
  35. minimum 6 znaków',
  36. 'required'=>'To pole jest wymagane')),
  37.  
  38. 'nowe_haslo'=>new sfValidatorString(
  39. array('required'=>true,
  40. 'min_length'=>6),
  41. array('min_length'=>'Hasło powinno składać się z
  42. minimum 6 znaków',
  43. 'required'=>'To pole jest wymagane')),
  44.  
  45.  
  46. 'nowe_powtorz'=>new sfValidatorString(
  47. array('required'=>true,
  48. 'min_length'=>6),
  49. array('min_length'=>'Hasło powinno składać się z
  50. minimum 6 znaków',
  51. 'required'=>'To pole jest wymagane')),
  52.  
  53. 'imie'=>new sfValidatorString(
  54. array('required'=>true,
  55. 'min_length'=>2),
  56. array('required'=>'To pole jest wymagane',
  57. 'min_length'=>'Imię powinno składać się z
  58. minimum 2 znaków')),
  59.  
  60. 'nazwisko'=>new sfValidatorString(
  61. array('required'=>true,
  62. 'min_length'=>2),
  63. array('required'=>'To pole jest wymagane',
  64. 'min_length'=>'Nazwisko powinno składać się z
  65. minimum 2 znaków')),
  66.  
  67. 'miasto'=>new sfValidatorString(
  68. array('required'=>false),
  69. array('required'=>'To pole jest wymagane')),
  70.  
  71. 'mail'=>new sfValidatorEmail(
  72. array(),
  73. array('invalid'=>'Zły adres email',
  74. 'required'=>'To pole jest wymagane'))
  75.  
  76.  
  77. ));
  78. //po metodzie POST
  79. $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
  80. new sfValidatorPropelUnique(
  81. array('model'=>'Uzytkownicy',
  82. 'column'=>'login'),
  83. array('invalid'=>'Podany login już istnieje')),


  1. new sfValidatorPropelUnique(
  2. array('model'=>'Rejestracja',
  3. 'column'=>'login'),
  4. array('invalid'=>'Podany login już istnieje')),
  5.  
  6. new sfValidatorSchemaCompare(
  7. 'nowe_haslo', sfValidatorSchemaCompare::EQUAL, 'nowe_powtorz',
  8. array(),
  9. array('invalid'=>'Hasła nie pasują do siebie!'))
  10.  
  11. )));//walidator unikalnego loginu i compare haseł
  12.  
  13.  
  14. }//koniec configure
  15. }//koniec klasy ChangeDataForm
  16.  
  17. //----------------akcja
  18.  
  19. public function executeEdit(sfWebRequest $request)
  20. {
  21. if($this->getUser()->isAuthenticated())
  22. {
  23. $id = $this->getUser()->getAttribute('id', null, 'uzytkownik');//pobieranie id usera
  24.  
  25. $c = new Criteria();
  26. $c->add(UzytkownicyPeer::USID, $id);
  27. $u = UzytkownicyPeer::doSelectOne($c);
  28.  
  29. if($this->getRequest()->isMethod('post'))//jezeli wyslano
  30. {
  31. $this->form = new ChangeDataForm();
  32. $this->form->bind(array('login'=>$this->getRequest()->getParameter('login'),
  33. 'stare_haslo'=>$this->getRequest()->getParameter('stare_haslo'),
  34. 'nowe_haslo'=>$this->getRequest()->getParameter('nowe_haslo'),
  35. 'nowe_powtorz'=>$this->getRequest()->getParameter('nowe_powtorz'),
  36. 'imie'=>$this->getRequest()->getParameter('imie'),
  37. 'nazwisko'=>$this->getRequest()->getParameter('nazwisko'),
  38. 'miasto'=>$this->getRequest()->getParameter('miasto'),
  39. 'mail'=>$this->getRequest()->getParameter('mail')
  40. ));
  41.  
  42.  


  1. if($this->form->isValid())//jezeli poprawny formularz
  2. {
  3.  
  4. if(md5($this->getRequest()->getParameter('stare_haslo') == $u->getHaslo()))//jezeli stare haslo sie zgadza
  5. {
  6. echo 'Haslo sie zgadza';...
  7. .................
  8. .......
  9. ...........//zapis do bazy itd.......................................
  10. }
  11.  
  12.  
  13. }//koniec valid if
  14. } else//ustawianie danych startowych
  15. {
  16. $this->form = new ChangeDataForm(array('login'=>$u->getLogin(),
  17. 'imie'=>$u->getImie(),
  18. 'nazwisko'=>$u->getNazwisko(),
  19. 'miasto'=>$u->getMiasto(),
  20. 'mail'=>$u->getMail()
  21. ));
  22.  
  23.  
  24. }//koniec request if
  25. }
  26. }//koniec executeEdit
  27.  
  28.  
  29.  


Chyba zaczynam powoli rozumieć mój problem....bo ja tworze nowy formularz i uzupełniam go danymi z jakiegoś tam wpisu i w momencie zapisu to jest traktowane jako nowy user a nie ten sam....potestuje to co Pr0100 napisał i zobaczę czy dam rade zrobić to co chcę. Rzeczywiście symfony musi traktować formularz jako formularz z danymi do edycji a nie formularz z danymi innego użytkownika, który potem przy zapisie próbuje stworzyć nowego usera. Jestem początkujący w symfony i poprostu wiele rzeczy rzutuje mi się jeszcze z obiektowego, zwykłego php, gdzie tworzyłem obiekty, zapisywałem dane do zmiennych a potem wykonywałem zapytania z udziałem tych zmiennych. Proszę o najjaśniejsze wyjaśnienie.
cojack
Jak dopiero zaczynasz z symfony, to od razu przerzuć się na doctrine a nie propela. Sam kiedyś mi za to podziękujesz.
blackroger
hmm...może spróbuje z doctrine przy następnym projekcie a teraz chciałbym dokończyć to co już zacząłem...
tutaj znalazłem praktycznie taki sam temat i rozwiązenie jak mój jakkolwiek nie wiem jak go wdrożyć u mnie.
http://forum.php.pl/lofiversion/index.php/t93454.html

Chodzi o walidację formularza do edycji danych użytkownika.
Próbowałem już tak jak pisał Pr0100 ale dalej jest to samo. tzn. dalej walidator krzyczy o unikalność loginów. Cały czas traktuje login tak jakby miał to być inny user a nie ten sam. Wiem że walidacja wykonuje się przed akcją zaraz po wysłaniu żądań. Jak ja mamto zrobić żeby działało...?
Pr0100
blackroger nie rozumiesz zupełnie idei formularzy w Symfony, wynajdujesz od nowa koło. http://www.symfony-project.org/forms/1_2/e...pel-Integration

Cytat
Jak dopiero zaczynasz z symfony, to od razu przerzuć się na doctrine a nie propela. Sam kiedyś mi za to podziękujesz.


warto znać oba ORM'y. A z Doctrine przesiadać się do propela to trochę jak z mercedesa do malucha smile.gif
yadue
Witam serdecznie,

mam także problem z sfValidatorPropelUnique:

kody:
  1. //rejestracja/actions.class.php
  2. <?php
  3.  
  4. /**
  5.  * rejestracja actions.
  6.  *
  7.  * @package sf_sandbox
  8.  * @subpackage rejestracja
  9.  * @author Your name here
  10.  * @version SVN: $Id: actions.class.php 12479 2008-10-31 10:54:40Z fabien $
  11.  */
  12. class rejestracjaActions extends sfActions
  13. {
  14. /**
  15.   * Executes index action
  16.   *
  17.   * @param sfRequest $request A request object
  18.   */
  19. public function executeIndex(sfWebRequest $request)
  20. {
  21. $formularz = new RegisterForm();
  22. if ($this->getRequest()->isMethod('post')) {
  23. $formularz->bind(array(
  24. 'login' => $this->getRequest()->getParameter('login'),
  25. 'haslo' => $this->getRequest()->getParameter('haslo'),
  26. 'powtorz' => $this->getRequest()->getParameter('powtorz'),
  27. 'imie' => $this->getRequest()->getParameter('imie'),
  28. 'nazwisko' => $this->getRequest()->getParameter('nazwisko'),
  29. 'miasto' => $this->getRequest()->getParameter('miasto'),
  30. 'mail' => $this->getRequest()->getParameter('mail')
  31. ));
  32.  
  33. if ($formularz->isValid()) {
  34. $dane = $this->formularz->getValues();
  35. $con = Propel::getConnection();
  36. try {
  37. $con->begin();
  38. $r = new Rejestracja();
  39. $r->setLogin($request->getParameter('login'));
  40. $r->setHaslo($request->getParameter('haslo'));
  41. $r->setMiasto($request->getParameter('miasto'));
  42. $r->setImie($request->getParameter('imie'));
  43. $r->setNazwisko($request->getParameter('nazwisko'));
  44. $r->setData(date("Y-m-d"));
  45. $r->setMail($request->getParameter('mail'));
  46. $r->save($con);
  47. $con->commit();
  48. return $this->forward("rejestracja/dziekujemy");
  49. } catch (Exception $e) {
  50. $con->rollback();
  51. return $this->forward("rejestracja/blad");
  52. }
  53. }
  54.  
  55. }
  56. $this->formularz = $formularz;
  57. }
  58. }
  59.  
  1. //rejestracja/lib/form/RegisterForm.php
  2. <?php
  3.  
  4. class RegisterForm extends sfForm {
  5. public function configure() {
  6. $this->setWidgets(array(
  7. 'login' => new sfWidgetFormInput(),
  8. 'haslo' => new sfWidgetFormInputPassword(),
  9. 'powtorz' => new sfWidgetFormInputPassword(),
  10. 'imie' => new sfWidgetFormInput(),
  11. 'nazwisko' => new sfWidgetFormInput(),
  12. 'miasto' => new sfWidgetFormInput(),
  13. 'mail' => new sfWidgetFormInput()
  14. ));
  15. $this->widgetSchema->setLabels(array(
  16. 'login' => 'Login:',
  17. 'haslo' => 'Hasło:',
  18. 'powtorz' => 'Powtórz hasło:',
  19. 'imie' => 'Imię:',
  20. 'nazwisko' => 'Nazwisko:',
  21. 'miasto' => 'Miasto:',
  22. 'mail' => 'E-mail:'
  23. ));
  24. $this->setValidators(
  25. 'login' => new sfValidatorPropelUnique(
  26. 'model' => 'Uzytkownicy',
  27. 'column' => 'login'),
  28. 'invalid' => 'Podany login już istnieje')),
  29. 'haslo' => new sfValidatorString(
  30. 'required' => true,
  31. 'min_length' => 4),
  32. 'invalid' => 'Hasło musi mieć minimum 4 znaki.')),
  33. 'imie' => new sfValidatorString(
  34. array('required' => false)),
  35. 'nazwisko' => new sfValidatorString(
  36. array('required' => false)),
  37. 'miasto' => new sfValidatorString(
  38. array('required' => false)),
  39. 'mail' => new sfValidatorAnd(
  40. new sfValidatorEmail(
  41. array('required' => true),
  42. array('invalid'=>'Zły adres E-Mail')),
  43. new sfValidatorPropelUnique(
  44. 'model' => 'Uzytkownicy',
  45. 'column' => 'login'),
  46. 'invalid' => 'Podany login już istnieje'))
  47. )),
  48.  
  49. ));
  50. $this->validatorSchema->setPostValidator(
  51. new sfValidatorSchemaCompare('haslo', '==', 'powtorz'));
  52. }
  53. }
  54.  
  55. ?>


Komunikat błędu:
You must pass an array parameter to the clean() method (this validator can only be used as a post validator).

Błąd dotyczy dokładnie lini 26 oraz 49. Bez nich względnie działa wszystko poprawnie, tzn nie ma błędu. Niestety nie mogę sobie poradzić z tym problemem. Jestem początkującym w Symfony (co w ogóle mnie oczywiście nie usprawiedliwia) i niestety nie mogę znaleźć rozwiązania tego problemu. Kod żywcem przepisany z książki niejakiego Pana Karola Przytalskiego, Symfony Aplikacje internetowe. Z góry dziękuję za pomoc i pozdrawiam
blackroger
Korzystam z tej samej książki i przechodzę niestety przez to samo i przez te same niejasne kody....
'login' => new sfValidatorPropelUnique jest post walidatorem i dlatego wyświetla błąd. Zobacz jak jest u mnie... Powracając do mojego problemu. Pr0100 pisząc mi że nie rozumiem zupełnie idei formularzy nie pomogło mi za wiele....Link który mi przesłałeś odnosi się bezpośrednio do klas propela generowanych automatycznie. A ja dziedziczę po sfForm...

Dobra problem rozwiązałem sam. Siedziałem nad tym 2 dni więc chcę to opisać. Piszę dla potomnych:

Jeżeli ktoś chce edytować dane i chce dać użytkownikowi możliwość zmiany np. loginu przy zachowaniu unikalności tego loginu w bazie z pominięciem wystąpienia błędu w przypadku braku zmiany unikalnego elementu, należy postąpić tak:

Można dziedziczyć zarówno po sfForm jak i BaseFormPropel. Po sfForm jest trochę uciążliwiej bo nie można ładować całego obiektu (np. UzytkownicyPeer::receiveByPk(2)) do konstruktora.

Cały problem leży w walidatorze który trzeba przypisać do klucza głównego.
Oto on:

'usid' => new sfValidatorPropelChoice(
array('model'=>'Uzytkownicy',
'column' => 'usid',
'required' => false))

Dzięki temu walidatorowi użytkownik jako obiekt łączy się z elementami i jest rozpoznawany przez propela jako całość.

Następną rzeczą, o której należy pamiętać jest umieszczenie widgeta 'usid' w templacie edycji w formularzu - najlepiej przy pomocy zdefiniowanego w Formie jako 'usid' => new sfWidgetFormInputHidden()
W ten sposób zapewnimy przesyłanie numeru obiektu użytkownika na naszą stronę.

Problemu nie ma się z tym w momencie korzystania z klas generowanych automatycznie, ponieważ tam ten walidator jest już automatycznie. W przypadku gdy dziedziczy się np. po sfForm problem jest.
Przy takim sposobie można do woli korzystać z sfValidatorPropelUnique np. dla loginu i będzie działał jak trzeba.
Zrozumiałem problem, dziękuję wszystkim za udział i próby pomocy.
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.