Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL][PDO] Bindowanie aby warunek był zawsze prawdziwy
Forum PHP.pl > Forum > Przedszkole
mlawnik
Witam,

mam poniższe zapytanie które pobiera dane do wykresu:
  1. $queryHandleSelect = $this->pdoHandle->prepare('SELECT gradeValue,gradeWeight FROM grades WHERE subjectId=:subjectId AND userId=:userId AND gradeTrimester = :gradeTrimester');

Użytkownik może podać, jakie subjectId sobie życzy, ale w przypadku jego braku chciałbym pobrać dane dla wszystkich subjectId.
Co powinienem poniżej zabindować?

  1. $queryHandleSelect->bindValue(':subjectId', 'questionmark.gifquestionmark.gifquestionmark.gifquestionmark.gif');


Bindowanie "subjectId" aby powstał warunek typu 1==1 nie działa w ten sposób:

  1. $queryHandleSelect->bindValue(':subjectId', 'subjectId');


Przypuszczam, że to w jaki sposób PDO binduje te dane ma wpływ, ale jak to zmienić?
Lub co innego jest błędne?

Pozdrawiam,
mlawnik
nospor
Gdy user nie poda tego ID to to: subjectId=:subjectId masz w ogole wywalic z zapytania i nic nie bindowac do tego
Crozin
Musisz wygenerować odpowiednie zapytanie, jedno z uwzględnieniem subjectId, drugie bez. W zależności od tego, którego będziesz używać musisz podpiąć kolejny parametr, bądź w ogóle nie brać go pod uwagę.
mlawnik
Czyli nie da się bez dwóch osobnych zapytań?
Crozin
Musisz albo przygotować sobie dwa osobne zapytania, albo budować zapytanie dynamicznie.
mmmmmmm
  1. $queryHandleSelect = $this->pdoHandle->prepare('SELECT gradeValue,gradeWeight FROM grades WHERE subjectId=:subjectId AND userId=:userId AND gradeTrimester = CASE WHEN :gradeTrimester="" THEN gradeTrimester ELSE :gradeTrimester END');
mlawnik
@mmm,

Zmieniłem sobie na bindowanie subjectId, ale najwyraźniej w PDO nie można zabindować jednej rzeczy do dwóch miejsc: "number of bound variables does not match number of tokens"

Jest jakiś sposób na obejście tego?


Dla potomnych:

Rozwiązanie z 2 różnymi query:
  1. if($this->chartSubject != NULL && !in_array($this->chartSubject, $this->userSubjects)){// first query
  2. $queryHandleSelect = $this->pdoHandle->prepare('SELECT gradeValue,gradeWeight FROM grades WHERE subjectId=:subjectId AND userId=:userId AND gradeTrimester = :gradeTrimester');
  3. //bind user id
  4. $queryHandleSelect->bindParam(':userId', $this->userId);
  5. //bind trimester
  6. if($this->chartTrimester == NULL){
  7. $queryHandleSelect->bindParam(':gradeTrimester', $this->currentTrimester); //
  8. }
  9. else{
  10. $queryHandleSelect->bindParam(':gradeTrimester', $this->chartTrimester);
  11. }
  12. $queryHandleSelect->bindValue(':subjectId', $this->chartSubject);
  13. }
  14. else{//second query no subject choice
  15. $queryHandleSelect = $this->pdoHandle->prepare('SELECT gradeValue,gradeWeight FROM grades WHERE userId=:userId AND gradeTrimester = :gradeTrimester');
  16. //bind user id
  17. $queryHandleSelect->bindParam(':userId', $this->userId);
  18. //bind trimester
  19. if($this->chartTrimester == NULL){
  20. $queryHandleSelect->bindParam(':gradeTrimester', $this->currentTrimester); //
  21. }
  22. else{
  23. $queryHandleSelect->bindParam(':gradeTrimester', $this->chartTrimester);
  24. }
  25. }

Rozwiązanie z 1 query:

  1.  
  2. $queryHandleSelect = $this->pdoHandle->prepare('SELECT gradeValue,gradeWeight FROM grades WHERE gradeTrimester=:gradeTrimester AND userId=:userId AND subjectId = CASE WHEN :subjectId="" THEN subjectId ELSE :subjectId2 END');
  3. $queryHandleSelect->bindParam(':userId', $this->userId);
  4. if($this->chartTrimester == NULL){
  5. $queryHandleSelect->bindParam(':gradeTrimester', $this->currentTrimester); //
  6. }
  7. else{
  8. $queryHandleSelect->bindParam(':gradeTrimester', $this->chartTrimester);
  9. }
  10. if($this->chartSubject != NULL && !in_array($this->chartSubject, $this->userSubjects)){
  11. $queryHandleSelect->bindValue(':subjectId', $this->chartSubject);
  12. $queryHandleSelect->bindValue(':subjectId2', $this->chartSubject);
  13. }
  14. else{
  15. $queryHandleSelect->bindValue(':subjectId', '');
  16. $queryHandleSelect->bindValue(':subjectId2', '');
  17. }
  18. $queryHandleSelect->execute();
  19. $this->chartData = $queryHandleSelect->fetchAll(PDO::FETCH_ASSOC);
nospor
@mmmmmmm mieszanie obecnosci zmiennej w zapytaniu jest moim zdanie totalnie bezsensu. Raz ze jest to bez sensu, dwa ze z kazdą kolejną zmienną jest to coraz bardziej nieczytelne.

@mlawnik Twoje rozwiązanie, gdzie generujesz oddzielne zapytania w zaleznosci od parametrow tez nie jest za dobre. Przy większej liczbie zmiennych parametrow zapultasz sie w stosie IF ELSE i w pewnym momencie zwątpisz.
To sie robi tak, iż w dynamiczny sposob generuje się jedno zapytanie dodajac do niego kolejne warunki w zaleznosci od parametrow. Tu masz przykladowe rozwiązanie:
http://nospor.pl/wyszukiwarka-zapytanie-za...d-warunkow.html
mlawnik
Czy ten sposób podany przez Ciebie można zastosować w połączeniu z PDO żeby się uchronić przed SQL Injection?
tzn. zbudować zapytanie i walnąć potem w PDO?
I czy nie ma jakichś mechanizmów które to obsługują "natywnie"?
nospor
Oczywiscie ze mozna podpiac to w majac PDO. Poprostu razem z budowaniem warunku budujesz tez tablicę bindowan.
Przejrzyj pare ostatnich temtow uzytkownika peklo, gdyz on to juz wlasnie podpinal pod PDO. Zobaczysz idee jak to sie robi z PDO.
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.