Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Klasa do połączeń i zapytań SQL
Forum PHP.pl > Forum > PHP
Zagiewa
Witam. Chcę stworzyć klasę do połączenia SQL w której będą też metody do zapytań jednak zależy mi na stworzeniu bardzo wydajnej klasy, a co więcej, żeby cały kod był dobrej jakości dlatego też ja mam pomysł i jakiś zalążek wiedzy, wy za to duże doświadczenie więc liczę, że mi trochę pomożecie smile.gif Głównym motywem na chwile obecną jest stworzenie metod, które będą generowane w zależności od tego co będziemy chcieli osiągnąć. Poniżej zamieszczę kod, który do tej pory napisałem, a pod nim pytania.

  1. <?php
  2.  
  3. class connection {
  4.  
  5. private $DB;
  6.  
  7. function __construct($DB_in) {
  8.  
  9. $this->DB = $DB_in;
  10. }
  11.  
  12. public function SQL_connect() {
  13.  
  14. include('static.php');
  15.  
  16. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  17. die("Sprawdź połączenie z serwerem! " . mysql_error());
  18. mysql_query("SET NAMES 'utf8'");
  19.  
  20. mysql_select_db($this->DB, $sql) or
  21. die("Sprawdź bazę! " . mysql_error());
  22. }
  23.  
  24. public function select_table($what_in, $from_in) {
  25.  
  26. $pobierz = "SELECT $what_in FROM $from_in";
  27. $result = mysql_query($pobierz) or
  28. die("Sprawdź rezultat! " . mysql_error());
  29.  
  30. while($row = mysql_fetch_array($result)) {
  31.  
  32. $a = $row[$what_in];
  33. echo $a. "<br />";
  34. }
  35. }
  36. }
  37.  
  38. ?>

  1. <?php
  2.  
  3. include('class.php');
  4. $connect = new connection("nazwa_bazy");
  5. $connect->SQL_connect();
  6. $connect->select_table("id", "nazwa_tabeli");
  7.  
  8. ?>

1. Chciałem aby można było za pomocą jednej metody łączyć się z różnymi bazami dlatego zanim wywołamy metodę SQL_connect() dzięki konstruktorowi podajemy, która baza nas interesuje. Teraz pytanie czy rozwiązanie to jest dobre? Czy może lepiej było by usunąć konstruktor i nazwę bazy podać bezpośrednio do metody czyli: SQL_connect("nazwa_bazy")?
2. Jak wiadomo zanim wykonamy jakiekolwiek operacje na tabelach w bazie trzeba się połączyć z bazą więc łączenie z SQL MUSI się odbyć prawda? więc zastanawiam się czy by nie zrezygnować z metody SQL_connect() i całość kodu wstawić w konstruktor wyglądało by to tak:
  1. function __construct($DB_in) {
  2.  
  3. $this->DB = $DB_in;
  4.  
  5. include('static.php');
  6.  
  7. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  8. die("Sprawdź połączenie z serwerem! " . mysql_error());
  9. mysql_query("SET NAMES 'utf8'");
  10.  
  11. mysql_select_db($this->DB, $sql) or
  12. die("Sprawdź bazę! " . mysql_error());
  13. }

Ma to sens? Mam jeszcze pytania odnośnie metody select_table() ale to innym razem. Jeśli macie ew. jakieś zastrzeżenia co do tego kodu to piszcie. Z góry dzięki smile.gif
tehaha
oprócz zastrzeżeń to nie wiele więcej zostaje, najlepiej używaj PDO, bo właśnie bo to jest, żebyś nie musiał pisać jakiejś beznadziejnej klasy, przede wszystkim to masz luki SQL Injection, po drugie nie daje się żadnego die() w przypadku błędu, poza tym taka metoda jest mało praktyczna jak pobieranie z jednej tabeli
Zagiewa
Z tym PDO to już jakiś standard? tzn zawsze się teraz tego używa czy to tylko jedna z możliwości? Tak czy inaczej właśnie mam zamiar przerobić swój kod na ten z wykorzystaniem PDO.
Chciałbym jednak zapytać o moją klasę tzn. napisałeś, że mam luki SQL Injection. Wiem co to jest jednak jestem ciekawy jakie luki widzisz w kodzie (będę miał nauczkę na przyszłość).
Napisałeś również żebym nie używał die() czemu?
tehaha
1. PDO po prostu został stworzony do obsługi bazy danych, jest wygodny, możesz używać różnych silników i podobno jest wydajny, kiedyś pisało się swoje klasy bo nie było wyboru.
2. co do sql injection to co tu dużo mówić jeśli coś wstawiasz do zapytania to musisz objąć to funkcją mysql_real_escape_string() albo używać prepered statements z PDO
3. czemu nie używać die()? Załóżmy, że napisałeś sobie serwis i przykładowo gdzieś tam w małym nie ważnym okienku robisz sobie funkcję :"Dzisiaj urodziny ma użytkownik tomek33!", i załóżmy, że z jakiegoś powodu skrypt wygenerował złe zapytanie i pojawia się błąd mysql, czy na pewno chcesz, żeby z powodu jakiejś pierdółki skrypt przerywał działania i wywalał napis "Sprawdź rezultat!"??
4. w klasach nie daje się echo, ani print() ani nic podobnego, funkcja powinna zwracać tablicę z wynikami, albo false w przypadku nie powodzenia.

Masz dużo błędów w logice, jeżeli chcesz to zrobić porządnie to najlepiej znajdź sobie jakąś fajną książkę
Zagiewa
Ad.2 Fakt zapomniałem kompletnie o tym, dzięki
Ad.3 Co do die() tak myślałem, że o to Ci chodzi jednak jest to zawsze jakiś sposób na sprawdzenie co jest nie tak.
Ad.4 Z tym się jeszcze nie spotkałem ale brzmi sensownie więc dzięki smile.gif

Ogólnie cały czas się uczę PHP więc wcale mnie błędy nie dziwią jednak właśnie dlatego utworzyłem temat aby dowiedzieć się gdzie robię błędy. Jak pisałem wcześniej chcę przerobić ten kod na ten z PDO jednak napotkałem pierwszy problem.

1. Gdy umieszczam kod:
  1. <?php
  2.  
  3. try
  4. {
  5. $pdo = new PDO('mysql:host=localhost;dbname=produkty', 'root', 'root');
  6. echo 'Połączenie nawiązane!';
  7. }
  8. catch(PDOException $e)
  9. {
  10. echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
  11. }
  12. ?>

Zmieniając oczywiście takie dane jak dbname itd. wyskakuje mi błąd: "could not find driver". Wiem też, że temat był poruszany na tym forum jednak wydaje mi się, że ja spełniam wszystkie warunki bo mam wersje PHP 5.2.5, a phpinfo() w PDO pokazuje mi, że mam włączony sterownik "sqlite2" więc powinno działać a jednak sad.gif co może jeszcze być nie tak?
tehaha
dam Ci jedną radę jak pojawia Ci się jakiś błąd i za bardzo nie wiesz co z nim zrobić to wpisujesz go w google lub wyszukiwarkę forum, zapamiętaj to bo to najważniejsza lekcja dla początkującego

@DOWN: no niestety w tym Ci nie pomogę bo sam nie wiem co jeszcze może nie grać
Zagiewa
I owszem zrobiłem tak zanim napisałem na forum i wszędzie pisze nawet na jednym z tematów na tym forum, że trzeba sprawdzić czy ma się włączoną obsługę extension=php_pdo_mysql.dll - mam. Druga sprawa to czy ma się PHP w wersji co najmniej 5.1 - mam. Czy phpinfo() pokazuje, że mamy włączone PDO - mam. Więc czego może jeszcze brakować? ale OK będę szukał dalej

OK mam. Miałem zakomentowane: extension=php_pdo_mysql.dll Teraz działa.

Ok więc korzystając z PDO udało mi się przekształcić poprzednią klasę na tą poniżej.
  1. <?php
  2.  
  3. class connection {
  4.  
  5. private $DB;
  6. private $what;
  7. private $from;
  8.  
  9. function __construct($DB_in, $what_in, $from_in) {
  10.  
  11. $this->DB = $DB_in;
  12. $this->what = $what_in;
  13. $this->from = $from_in;
  14. }
  15.  
  16. public function select_table() {
  17.  
  18. include('static.php');
  19.  
  20. try {
  21.  
  22. $pdo = new PDO('mysql:host=' .SQL_HOST. ';dbname=' .$this->DB. '', SQL_USER, SQL_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  23. $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  24.  
  25. $stmt = $pdo -> query('SELECT ' .$this->what. ' FROM ' .$this->from. '');
  26.  
  27. foreach($stmt as $row) {
  28.  
  29. $a = $row[$this->what];
  30. echo $a. "<br />";
  31. }
  32.  
  33. $stmt -> closeCursor();
  34. }
  35.  
  36. catch(PDOException $e) {
  37.  
  38. echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
  39. }
  40. }
  41. }
  42.  
  43. ?>

  1. <?php
  2.  
  3. include('class.php');
  4. $connect = new connection("nazwa_bazy", "id", "nazwa_tabeli");
  5. $connect->select_table();
  6.  
  7. ?>

Jednak pisząc to zaczęły pojawiać się pytania...
tehaha - do mojej poprzedniej klasy wspomniałeś o luce SQL_Injection i że brakuje mi mysql_real_escape_string() gdy zastosowałem tą funkcję do obecnej klasy dla którejkolwiek zmiennej (DB, what, from) otrzymałem błąd. Co do tego błędu to jeszcze się zajmę nim później ale moje pytanie - czy PDO jest bezpieczne od SQL_injection?
Druga sprawa to czy muszę za każdym razem łączyć się z bazą gdy chcę utworzyć nowe zapytanie? Bo gdy chciałem utworzyć jedną metodę do łączenia się z bazą, a drugą z zapytaniem o konkretną tabelę to nie działało - zrobiłem błąd czy tak ma być?
mg2
Obiekt $pdo jest połączeniem do bazy. Rozłączasz się z bazą przypisując mu wartość null, czyli kasując odpowiadającą mu referencję.

Z bazą łączysz się, jeżeli chcesz wykonać zapytanie a nie jesteś z nią połączony;) Czyli jak się po pierwszym zapytaniu nie rozłączysz to możesz ich wykonywać ile chcesz i ponownie łączyć się nie musisz.

PDO jest bezpieczne jeżeli będziesz go używał tak jak w example 7: http://www.php.net/manual/en/pdo.prepared-statements.php używając bindowania. Wtedy zapytanie jest takim niby szablonem do którego wstawiane są przy wykonywaniu odpowiednie dane i prawodpodobnie zabezpiecza to w stu procentach przed zmianą zapytania poprzez wstawienie przez użytkownika odpowiednio spreparowanych danych.


Ogólnie to wydaje mi się że nie powinieneś kombinować z pisaniem dodatkowych klas tylko korzystać bezpośrednio z pdo, bo to trochę jakbyś chciał uokrąglać koło żeby się lepiej kręciło;)



Co do samego pisania klas, wydaje mi się że powinno się unikać dołączania plików w klasach a zwłaszcza w ich metodach bo to zmniejsza elastyczność. Już chyba lepiej byłoby te dane bazy podać konstruktorowi tej klasy jako argumenty.
darko
Dziedzicz po klasie PDO dodając jakieś pożądane funkcjonalności, a nie robisz kompozycję. W przypadku PDO mysql_real_escape_string() nie jest już potrzebne, ani żaden filtr dodatkowy, wystarczy poprawne preparowanie i bindowanie.
Zagiewa
Dziś już jestem zbyt zmęczony na dalsze pisanie kodu więc wolę jutro się tym zająć ale odnośnie tego co napisaliście:

mg2 - "Z bazą łączysz się, jeżeli chcesz wykonać zapytanie a nie jesteś z nią połączony;)" masz racje, źle to sformułowałem.
Napisałeś też abym nie robił klas tylko bezpośrednio korzystał z PDO masz na myśli żebym wklepywał PDO bezpośrednio w kod wszędzie tam gdzie będę potrzebował wysłać zapytanie do bazy? jeśli tak to takie rozwiązanie jest myślę mało efektowne bo gdy okaże się, że mam błąd to będę musiał uruchamiać "x" plików w których użyłem PDO aby poprawić błąd. Gdy będzie on w klasie bądź nawet funkcji którą includuje wystarczy, że zmienię raz.

"... Już chyba lepiej byłoby te dane bazy podać konstruktorowi tej klasy jako argumenty." - czy nie jest bezpieczniej gdy one leżą sobie gdzieś w pliku jako stałe?

darko - "Dziedzicz po klasie PDO dodając jakieś pożądane funkcjonalności, a nie robisz kompozycję." Nie bardzo rozumiem co masz na myśli. A co do mysql_real_escape_string() to by tłumaczyło dlaczego wyskakiwał mi ten błąd smile.gif
d3ut3r
PDO to właśnie klasa której powinieneś używać, nie bardzo zrozumiałem twój argument z błędem i edycją x plików ale raczej masz mylne wyobrażenie o tym jak to powinno wyglądać. To o czym piszesz to taki pseudo model czyli klasa która będzie wykonywać zapytania możesz np napisać klasę auta a w niej metody dodajAuto usunAuto policzAuta a w tych metodach używasz PDO do komunikacji z bazą danych. I w momencie gdy wykonujesz operacje na autach w dowolnym miejscu skryptu tworzysz obiekt klasy auta i uruchamiasz odpowiednie metody jeżeli będziesz miał błąd w zapytaniu to poprawiasz go tylko w jednym miejscu czyli w twojej klasie auta.
Zagiewa
d3ut3r - dokładnie o to mi chodzi. Chcę aby PDO było tylko w jednym pliku i żebym mógł tylko w odpowiednich miejscach się do niej odwoływać tworząc obiekty. Czyli takie rozwiązanie (metoda pobierania danych z tabeli za pomocą PDO) jest poprawna?

OK posiedziałem trochę przy art odnośnie bindowania. Czytałem o tym w manualu PHP oraz WikiBooks jednak dużo więcej przykładów można spotkać przy wstawianiu danych do bazy (INSERT). Korzystałem nawet z tego tematu: http://forum.php.pl/index.php?showtopic=57510 jednak to też dla INSERT. Przez brak większej ilości informacji na temat pobierania danych mam problem. Chcę bindować dane przesłane do zapytania (co pobierać i skąd pobierać) i dostaje błąd sad.gif cały czas nad tym siedzę więc może uda mi się jakoś dojść do tego ale zamieszczam kod poniżej, może szybciej się doszukacie błędu.
  1. <?php
  2.  
  3. class connection {
  4.  
  5. private $DB;
  6. private $what;
  7. private $from;
  8.  
  9. function __construct($DB_in, $what_in, $from_in) {
  10.  
  11. $this->DB = $DB_in;
  12. $this->what = $what_in;
  13. $this->from = $from_in;
  14. }
  15.  
  16. public function select_table() {
  17.  
  18. include('static.php');
  19.  
  20. try {
  21.  
  22. $pdo = new PDO('mysql:host=' .SQL_HOST. ';dbname=' .$this->DB. '', SQL_USER, SQL_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  23. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  24.  
  25. $stmt = $pdo->prepare('SELECT :what FROM :from');
  26. $stmt->bindParam(':what', $this->what, PDO::PARAM_STR);
  27. $stmt->bindParam(':from', $this->from, PDO::PARAM_STR);
  28. $stmt->execute();
  29.  
  30. while($row = $stmt->fetch()) {
  31.  
  32. $a = $row[$this->what];
  33. echo $a. "<br />";
  34. }
  35.  
  36. $stmt -> closeCursor();
  37. }
  38.  
  39. catch(PDOException $e) {
  40.  
  41. echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
  42. }
  43. }
  44. }
  45.  
  46. ?>

Błąd jaki dostaje to:
SQLSTATE[42000]: Syntax error or access violation: 1064 Something is wrong in your syntax obok ''artykuly'' w linii 1
Od razu mówię, że szukałem w google czegoś na temat tego błędu jednak nie znalazłem żadnej odpowiedzi.
greycoffey
Tak, szukałeś, ja tu widzę rozwianie.. Kliknij!

Generalnie zapoznaj się z PDO dokładniej, nie twórz żadnej klasy proxy niby-automatyzującej pracę, chyba że chcesz dodać jakąś bardzo ważną funkcjonalność - zobacz TO.
Zagiewa
greycoffey - piękna animacja, podoba mi się jednak przyglądnij się tym stronom smile.gif odpowiedzi na mój problem tam nie ma. Co do reszty tego co napisałeś, zaraz się tym zajmę.

Masz racje, nie będę tworzył jakiś dziwnych modyfikacji, a raczej będę używał najprostszych zapytań więc zrezygnowałem z klasy dodatkowe. Cały czas siedzę w specyfikacji PDO (zgodzę się z tym, że im więcej się dowiem o PDO tym lepiej to zrozumiem dlatego cały czas czytam o tym). Jednak poniższy kod dalej nie działa, chociaż uprościłem go już chyba maksymalnie sad.gif otrzymuje błąd:
SQLSTATE[42000]: Syntax error or access violation: 1064 Something is wrong in your syntax obok ''artykuly'' w linii 1
I na prawdę nie mogę znaleźć odpowiedzi jak to poprawić. Poniżej kod:
  1. <?php
  2.  
  3. $what = "tytul";
  4. $from = "artykuly";
  5.  
  6. include('static.php');
  7.  
  8. try {
  9.  
  10. $pdo = new PDO('mysql:host=' .SQL_HOST. ';dbname=' .SQL_DB, SQL_USER, SQL_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  11. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  12.  
  13. $stmt = $pdo->prepare('SELECT :what FROM :from');
  14. $stmt->bindParam(':what', $what, PDO::PARAM_STR);
  15. $stmt->bindParam(':from', $from, PDO::PARAM_STR);
  16. $stmt->execute();
  17.  
  18. while($row = $stmt->fetch()) {
  19.  
  20. $a = $row[$what];
  21. echo $a. "<br />";
  22. }
  23.  
  24. $stmt -> closeCursor();
  25. }
  26.  
  27. catch(PDOException $e) {
  28.  
  29. echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
  30. }
  31.  
  32. ?>

Jedyne co zauważyłem, że jeśli usunę: $stmt->bindParam(':from', $from, PDO::PARAM_STR); i w zapytaniu, zamiast: :from wstawię po prosty "artykuly" działa ale zamiast wyświetlić mi ileś tam tytułów jeden pod drugim wyświetla mi wartość zmiennej $what co wygląda to:

tytul
tytul
tytul
... itd.
darko
Zdaje się, że ta linia
  1. $stmt = $pdo->prepare('SELECT :what FROM :from');

powoduje problem. Z tego, co pamiętam, nie wolno było parametryzować nazw kolum, czyli tego, co chcesz wyciągnąć. Pewnie takie zapytanie będzie poprawne:
  1. $stmt = $pdo->prepare('SELECT * FROM :from');
Zagiewa
darko dobrze kombinujesz i też tak próbowałem... jednak gdy zrobię tak jak napisałeś czyli zrezygnuję z
  1. $stmt->bindParam(':what', $what, PDO::PARAM_STR);

Nie daje żadnej poprawny jednak gdy to zostawię, a usunę:
  1. $stmt->bindParam(':from', $from, PDO::PARAM_STR);

to już działa czyli prędzej PDO nie lubi jak się od razu mu nie poda w jakiej tabeli chcemy szukać. Gdy jednak na stale wpisze mu:
  1. $stmt = $pdo->prepare('SELECT :what FROM artykuly');

To błąd znika ale otrzymuję zły wynik zapytania. Zamiast wyświetlić mi ileś tam tytułów jeden pod drugim wyświetla mi wartość zmiennej $what co wygląda to:

tytul
tytul
tytul
... itd.

OK szybkie wnioski... Gdy zamiast wstawiania za pomocą bindowania co chcę pobrać (zmienna $what) i w jakie tabeli (zmienna $from) wstawię na stale te dane, zapytanie wygląda wtedy tak:
  1. $stmt = $pdo->prepare('SELECT tytul FROM artykuly');

Wszystko działa prawidłowo. Moje pytanie brzmi: Czy zapytanie typu SELECT nie może przyjmować danych tak jak to robiłem wcześniej aby działało poprawnie? Bo metodą prób i błędów dochodzę do wniosku, że nie moze. Szkoda tylko, że nie udało mi się do tej pory znaleźć ani jednego przykładu, który pokazuje wstawianie danych do zapytania SELECT w postaci zmiennych, ani też informacji o tym, że nie wolno tego robić.

Idąc dalej tym tropem, stworzyłem też za pomocą PDO i bindowania zapytanie typu INSERT. Gdy w miejscu VALUES() wstawię zmienne zapytanie działa poprawnie jednak gdy zmienne chcę wstawić w INTO zapytanie już nie działa. Krótko mówiąc metodą prób i błędów osiągnąłem ten sam wynik. PDO nie lubi jak próbujemy wstawić zmienne w miejsca takie jak: co pobieramy, skąd pobieramy itp.
darko
Racja oczywiście nie wolno parametryzować nazw tabel. W manualu też nie znalazłeś, w jaki sposób poprawnie korzystać z PDO?
//edit
edytowałem tego posta, bo to, co Ci napisałem było zbytnim uogólnieniem.
Zagiewa
OK zgodzę się z tym, że bindowanie ma na celu zabezpieczenie danych "przychodzących" aby nie zostało wykonane niewłaściwe zapytanie. Ale teraz mam pytanie do wszystkich tych który kiedykolwiek tworzyli zapytania.

Duże serwisy mają dziesiątki albo i nawet setki różnych zapytać. Ja próbowałem stworzyć jedno (pewnego rodzaj schemat) do którego wstawiał bym dane w zależności od tego co bym chciał osiągnąć. Coś na zasadzie funkcji/metody - jest jedna metoda z zapytaniem np. SELECT która przyjmuje wartośći i od tych wartości zależy co i gdzie zostanie wykonane. Rozwiązanie to miało zapobiec pisaniu całych nowych zapytań. Czy da się stworzyć taką funkcję/metodę która będzie w ten sposób działać czy nawet w dużych projektach tworzy się za każdym razem nowe zapytanie? Schematy te chciałem aby wyglądały (w dużym uproszczeniu) tak:
  1. SELECT $co FROM $gdzie
  2. INSERT INTO $gdzie VALUE($co)
  3. UPDATE $gdzie SET $kolumna=$wartosc WHERE $kolumna=$jakas_wartosc


darko - w manualu jest masa informacji na temat PDO i cały czas w tym siedzę jednak odpowiadając na pytanie czy nie znalazłem informacji na temat tego, że nie wolno parametryzować tabel - nie, nie znalazłem. Żaden z przykładów, które widziałem (a było ich trochę...) nie pokazywał parametryzacji tabel więc można było wywnioskować, że się nie da ale szukałem dalej z nadzieją, że może jednak da się to jakoś zrobić
darko
Efekt, o który pytasz uzyskuje się za pomocą metod:
prepare (wykonujesz raz)
(opcjonalnie po drodze bind)
execute (później np. w pętli wielokrotnie wywołujesz w każdej iteracji z innymi parametrami)
na końcu fetchXXX
Przyśpiesza to wyciąganie danych, gdyż zapytanie jest cacheowane (preinterpretowane).
Zagiewa
Więc twierdzisz, że się da stworzyć taki schemat? no ale widzisz gdy ja chciałem go zrobić nie udało mi się. Sam napisałeś, że nie wolno preparować nazw tabeli więc owszem mogę wstawiać różne wartości tylu VALUE ale nic po za tym, a to tak jak by połowa sukcesu. No chyba, że źle Cię zrozumiałem.
darko
Mam wrażenie, że sam sobie nieco utrudniasz życie. Nikt Ci nie każe preparować nazw tabel, ani nazw poszczególnych kolumn, gdyż - można powiedzieć, że - dane, które pochodzą od Ciebie są zaufane i można je spokojnie wstawiać (konkatenować) bezpośrednio do treści zapytań, uzyskując efekt, o którym wcześniej napisałeś (parametryzacja nazw kolumn i tabel), prosty przykład:

  1. function pdo_select_all(PDO $pdo, $co = null, $gdzie = null)
  2. {
  3. $return = false;
  4. // SELECT $co FROM $gdzie
  5. if(!is_null($co) && !is_null($gdzie))
  6. {
  7. $sth = $pdo->prepare('SELECT ' . $co . ' FROM ' . $gdzie);
  8. $sth->execute();
  9. $return = $sth->fetchAll();
  10. $sth->closeCursor();
  11. }
  12. return $return;
  13. }
  14.  
  15. print_r(pdo_select_all($pdo, $what, $from));
  16. // gdzie $pdo to obiekt klasy PDO


Preparowania i bindowania używa się na danych pochodzących z zewnątrz, w celu uniknięcia potencjalnego zagrożenia ze strony nieuczciwych użytkowników. Ponieważ nie można preparować nazw tabel (gdyż są one w zapytaniach quotowane) najlepiej bindować tylko te dane, co do których mamy pewność, że mogą stanowić potencjalne zagrożenie dla zapytania, czyli generalnie wszystko to, co pochodzi od użytkowników. A więc w przypadku wyciągania danych, bindujemy tylko cześć warunku następującą po WHERE, ewentualnie wartość LIMIT, jeżeli oczywiście limitujemy wyniki. Mam nadzieję, że nieco Ci wytłumaczyłem, na czym problem polega i podsunąłem odpowiednią wskazówkę, w jaki sposób można osiągnąć efekt, o który pytasz. Przyznam, że dawno nie korzystałem z "gołego" PDO, natomiast z tego, co pamiętam w Zendzie była klasa Zend_Db_Expr, która pozwalała na bezpośrednie parametryzowanie fragmentów zapytań np. new Zend_Db_Expr('COUNT(schema1_lines.id) AS lines')) dzięki czemu można było uniknąć quotowania.
Zagiewa
darko masz racje można wstawić w zapytanie zmienne i wiedziałem o tym ale przez to całe zamieszanie z bindowaniem (bo robię to po raz pierwszy) porąbało mi się i faktycznie niepotrzebnie chciałem bindować wszystko. Przyznaję się do błędu smile.gif Mówiąc inaczej... niektóre dane będą szły do zapytania z formularza i te trzeba bindować ale będą do dane tylu VALUE() natomiast na pewno takie dane jak nazwa kolumny bądź nazwa tabeli nie będzie pochodzić z formularza a ze zmiennej którą w końcu sam napisze więc bindowanie jest zbędne smile.gif

Przepraszam raz jeszcze bo to efekt zamotania smile.gif

Myślę, że wszystko co chciałem wiedzieć, a nawet więcej, już wiem co nie zmienia faktu, że to nie koniec mojej zabawy z PDO więc być może jeszcze poruszę ten temat lecz na chwile obecną dziękuję wszystkim za pomoc, oczywiście "pomógł" wystawie 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.