![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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 (IMG:style_emoticons/default/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. 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:
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 (IMG:style_emoticons/default/smile.gif) |
|
|
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 1 748 Pomógł: 388 Dołączył: 21.08.2009 Skąd: Gdynia Ostrzeżenie: (0%) ![]() ![]() |
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
|
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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? |
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 1 748 Pomógł: 388 Dołączył: 21.08.2009 Skąd: Gdynia Ostrzeżenie: (0%) ![]() ![]() |
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ę |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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 (IMG:style_emoticons/default/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:
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 (IMG:style_emoticons/default/sad.gif) co może jeszcze być nie tak? |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 1 748 Pomógł: 388 Dołączył: 21.08.2009 Skąd: Gdynia Ostrzeżenie: (0%) ![]() ![]() |
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ć Ten post edytował tehaha 22.02.2011, 23:10:20 |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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.
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ć? Ten post edytował Zagiewa 23.02.2011, 00:15:32 |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 2 Pomógł: 1 Dołączył: 19.02.2011 Ostrzeżenie: (0%) ![]() ![]() |
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. |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
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.
|
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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 (IMG:style_emoticons/default/smile.gif) |
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 709 Pomógł: 176 Dołączył: 24.10.2010 Ostrzeżenie: (0%) ![]() ![]() |
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.
|
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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 (IMG:style_emoticons/default/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.
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. Ten post edytował Zagiewa 23.02.2011, 18:49:26 |
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 320 Pomógł: 29 Dołączył: 3.04.2010 Ostrzeżenie: (20%) ![]() ![]() |
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. |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
greycoffey - piękna animacja, podoba mi się jednak przyglądnij się tym stronom (IMG:style_emoticons/default/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 (IMG:style_emoticons/default/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:
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. Ten post edytował Zagiewa 23.02.2011, 20:43:27 |
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Zdaje się, że ta linia
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:
Ten post edytował darko 24.02.2011, 04:06:26 |
|
|
![]()
Post
#16
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
darko dobrze kombinujesz i też tak próbowałem... jednak gdy zrobię tak jak napisałeś czyli zrezygnuję z
Nie daje żadnej poprawny jednak gdy to zostawię, a usunę:
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:
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:
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. Ten post edytował Zagiewa 24.02.2011, 13:09:16 |
|
|
![]()
Post
#17
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
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. Ten post edytował darko 24.02.2011, 14:04:14 |
|
|
![]()
Post
#18
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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:
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ć Ten post edytował Zagiewa 24.02.2011, 14:17:06 |
|
|
![]()
Post
#19
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
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). |
|
|
![]()
Post
#20
|
|
Grupa: Zarejestrowani Postów: 84 Pomógł: 0 Dołączył: 12.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
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.
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 14.09.2025 - 14:55 |