Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP] PDO wprawiające w zakłopotanie
SlimShady
post
Post #1





Grupa: Zarejestrowani
Postów: 29
Pomógł: 0
Dołączył: 11.05.2013

Ostrzeżenie: (0%)
-----


Hej Wam,

od jakiegoś czasu, swoje skrypty opieram o bibliotekę PDO. Bardzo ją lubię, tworzenie przy niej kodu sprawia mi większą przyjemność niż korzystanie z klasycznego mysql_*. Jednak z powodu dość rzadkiego opisu posługiwania się nią, jest wiele kwestii, które budzą u mnie niepewność i zaciekawienie. Wiem, że są takie rzeczy jak manual, osobiście sam jestem wielkim zwolennikiem kopania danego hasła w google, aczkolwiek tym razem nie mogę nakierować się na odpowiednią ścieżkę.

Tak więc, ciekawią mnie 2 rzeczy:
1. Kiedy mam wykorzystać $query->fetchAll(), zamiast normalnego $query->fetch(). Z tego co mój mózg wnioskuję, jeśli chcę przypisać sobie do zmiennej wszystkie wyniki pewnego zapytania, wtedy korzystam z fetchAll i mam do dyspozycji wszelkie pobrane rekordy, w jednym zasobniku - czy na pewno?

2. Do czego jest tryb zwracania wyników PDO::FETCH_OBJ? Wiem o nim tyle, że przedstawienie wyników, odbywa się w postaci anonimowego obiektu, o własnościach nazw pól. Ale w jakiej konkretnie sytuacji może on się okazać przydatny? Oraz, czy zdefiniowanie samego PDO::FETCH_ASSOC lub PDO::FETCH_NUM, zwracającego tablicę indeksowaną asocjacyjnie/numerycznie, jest wydajniejsze/szybsze niż to i to łączne (PDO::FETCH_BOTH)?
I jeśli zapiszę $query->fetchObject() oraz $query->fetch(PDO::FETCH_OBJ) da mi to identyczny efekt?

Pozdrawiam (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 11)
SmokAnalog
post
Post #2





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Fajne pytania, lubię ludzi, którzy rozkminiają (IMG:style_emoticons/default/smile.gif)
  1. Tak jak zauważyłeś, fetchAll zapisuje wszystkie wyniki do tablicy. Przydaje się to wtedy, kiedy... chcesz wszystkie wyniki w tablicy (IMG:style_emoticons/default/smile.gif) Jak iterujesz wiele rekordów, to raczej rzadko chcesz zapisać wszystko w tablicy, a fetch() oszczędza pamięć jadąc wiersz po wierszu. Przykłady kiedy mógłbyś użyć fetchAll()? Może np. wykonujesz jakieś zapytanie i wyświetlasz dane w kilku miejscach różnie posortowane - zamiast osobnych zapytań do bazy możesz wtedy bawić się tablicą z danymi. Oprócz tego wszelkie wypluwanie danych, np. do formatu JSON - przekazujesz całą tablicę do funkcji formatującej. Przykładów może być bardzo wiele.
  2. To już jest głównie kwestia preferencji. Osobiście wolę pracować z tablicą asocjacyjną niż z obiektem, chociaż odczyt danych odbywa się w dość podobny sposób. W obu możesz odwoływać się do określonego pola po nazwie. Tablicę możesz dodatkowo sortować, a obiektu nie. FETCH_NUM jest prawdopodobnie nieco bardziej wydajne niż FETCH_ASSOC, ale są to różnice kompletnie niewarte świeczki. Ja używam tylko FETCH_ASSOC, bo nie widzę sensu w odwoływaniu się do kolumn po indeksach. FETCH_BOTH tworzy większą tablicę z wynikami - nigdy tego nie używam (choć nie z tego powodu). Co do fetchObject to tak, daje to identyczny efekt jak FETCH_OBJ, co jest wyraźnie zaznaczone w oficjalnej dokumentacji.
Go to the top of the page
+Quote Post
SlimShady
post
Post #3





Grupa: Zarejestrowani
Postów: 29
Pomógł: 0
Dołączył: 11.05.2013

Ostrzeżenie: (0%)
-----


jak ja lubię ludzi, którzy mnie rozumieją (IMG:style_emoticons/default/biggrin.gif)

poczułem się w pełni usatysfakcjonowany, jedyne co pozostało mi do szczęścia, to jeszcze jedna.. mała kwestia.. w zasadzie to 2 małe kwestię, które warto tu chyba podpiąć, a jak jest okazja, to chciałbym być jak najbardziej pewny swojej wiedzy.

1. Ten temat spotykany był wiele razy, m.in. zamknięcie wskaźnika zapytania. Według mojego rozumowania, $query->closeCursor(); powinienem umieszczać wszędzie, gdzie zarządzam nie całą liczbą wcześniej pobranych rekordów (np. nie po fetchAll), czy to znaczy, że obejmuję to także polecenia INSERT, UPDATE etc?
2. Czy zapis:
  1. if ($query->rowCount() == 0)

jest najszybszym sposobem sprawdzenia, czy zapytanie z INSERT dodało nowy rekord?
ew. myślałem o takim sposobie:
  1. if (!isset($db->lastInsertId))

ale to chyba jednak, nie jest wcale lepsze rozwiązanie..?

Ten post edytował SlimShady 6.07.2013, 23:32:24
Go to the top of the page
+Quote Post
Mackos
post
Post #4





Grupa: Zarejestrowani
Postów: 362
Pomógł: 44
Dołączył: 10.06.2009

Ostrzeżenie: (0%)
-----


Cytat(SmokAnalog @ 7.07.2013, 00:11:47 ) *
lubię ludzi, którzy rozkminiają

Cytat
jak ja lubię ludzi, którzy mnie rozumieją

(IMG:style_emoticons/default/heart.gif) (wybaczcie - nie mogłem się powstrzymać).

A tak co do tematu to chyba lepiej tak:
  1. if ($pdo->execute())
  2. return true;
  3. else
  4. return false;
Go to the top of the page
+Quote Post
SmokAnalog
post
Post #5





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


(IMG:style_emoticons/default/zakochany.gif)

Mackos, Twój zapis to PHP-owe masło maślane. Wystarczy:
  1. return $pdo->execute();


Jeśli chcesz po prostu sprawdzić czy rekord dodał się prawidłowo, to rzeczywiście wystarczy:
  1. if($query->execute()) {
  2. // udało się dodać do bazy
  3. }


Jeśli dodatkowo chcesz wiedzieć ile dokładnie dodało się rekordów, to rowCount() jest dobrym pomysłem.

Co do kursora, nie do końca rozumiem pytanie. Dokumentacja szczegółowo wyjaśnia działanie closeCursor() - ja tego nigdy nie używałem, a do tej pory nawet nie znałem. Z tego co zrozumiałem, to to się przydaje tylko wtedy, kiedy chcesz kilkukrotnie przeiterować wyniki zapytania, kiedy nie iterujesz całego zestawu wyników. Czyli np. zapytanie zwraca 10 wierszy, a Ty iterujesz w pierwszej porcji 5, w następnej 7, potem 2 itd. Co więcej, dokumentacja twierdzi, że resetowanie kursora to jest domyślne zachowanie wielu systemów baz danych, czyli w nich execute() samo resetuje kursor. Nie zawracałbym sobie głowy tym closeCursor(). A już na pewno nieprzy INSERT i UPDATE - tych zapytań nawet się nie iteruje, prawda? One się po prostu wykonują.
Go to the top of the page
+Quote Post
SlimShady
post
Post #6





Grupa: Zarejestrowani
Postów: 29
Pomógł: 0
Dołączył: 11.05.2013

Ostrzeżenie: (0%)
-----


ale ze mnie nieogarnięta istota.. nie pomyślałem nawet, że zwyczajnie samo wykonanie zwróci mi wartość logiczną, eh dzięki chłopaki (IMG:style_emoticons/default/tongue.gif)

co do closeCursor() - spotkałem się już nie jednokrotnie z zaleceniem jego zastosowania i to nie tylko pod pretekstem "zezwolenia" na kolejne, ale co najciekawsze, natrafiłem również na taką notkę:
"w niektórych przypadkach (driver-specific) zwiększa wydajność", oraz głównie, że polepsza to kompatybilność nad innymi systemami baz danych.

i bądź tu mądry (IMG:style_emoticons/default/ohno-smiley.gif)

ostatecznie - chyba się jednak jego pozbędę (IMG:style_emoticons/default/wink.gif)
jeszcze raz dzięki.

Ten post edytował SlimShady 6.07.2013, 23:59:01
Go to the top of the page
+Quote Post
markonix
post
Post #7





Grupa: Zarejestrowani
Postów: 2 707
Pomógł: 290
Dołączył: 16.12.2008
Skąd: Śląsk

Ostrzeżenie: (0%)
-----


Może się podepnę bo o ile różnice pomiędzy $query->fetchAll(), a $query->fetch() dobrze rozumiem to zastanawiam się nad tym, co powinny zwracać w zaawansowanej aplikacji (np. jakiś framework) metody (funkcje) typu getCośTam. Np. funkcja getUsers - czyli metoda modelu użytkowników zwracająca listę użytkowników.
No i teraz pytanie - zawsze zwracam tablicę obiektów bo wydaje mi się to wygodne i logiczne ale nie jest to optymalne właśnie porównując do iteracji po wierszach.

Jak to rozwiązujecie? Optymalność vs logika, wygoda?
Go to the top of the page
+Quote Post
ber32
post
Post #8





Grupa: Zarejestrowani
Postów: 332
Pomógł: 22
Dołączył: 6.07.2010

Ostrzeżenie: (0%)
-----


Witam.
Cytat
ostatecznie - chyba się jednak jego pozbędę

Już ci mogę powiedzieć że będzie to wielki błąd. Poczytaj jeszcze raz gdzie się tego używa. Sprawdź także na większej ilości zapytań select i będziesz wiedział że faktycznie to błąd.

W niektórych przypadkach jest to niezbędne.

Ten post edytował ber32 7.07.2013, 16:50:46
Go to the top of the page
+Quote Post
SlimShady
post
Post #9





Grupa: Zarejestrowani
Postów: 29
Pomógł: 0
Dołączył: 11.05.2013

Ostrzeżenie: (0%)
-----


Bardzo dziękuje za wypowiedzenie się, teraz mam takie dziwne odczucie i nie wiem, gdzie powinienem je umieścić w następującym kodzie:
  1. //przygotowujemy zapytanie, które ma sprawdzić istnienie już takiego konta
  2. $check = $db->prepare("SELECT id FROM star_users WHERE user = :login OR mail = :mail");
  3. //przefiltrowujemy wpisane dane
  4. $check->bindValue(':login', $_POST['user'], PDO::PARAM_STR);
  5. $check->bindValue(':mail', $_POST['mail'], PDO::PARAM_STR);
  6.  
  7. //wykonujemy zapytanie i sprawdzamy rezultat
  8. if ($check->execute()) echo 'Takie konto już istnieje..';
  9. else {
  10. //jakieś operacje
  11. header('Location: przekierowanie');
  12. }
  13.  


W którym miejscu w powyższym kodzie, mogę 'zaaranżować' closeCursor()? Myślałem o przestrzeni nazwanej (IMG:style_emoticons/default/questionmark.gif) , jednak nie wiem, czy wówczas PHP uwzględni je z przekierowaniem i czy będzie to tam potrzebne, oraz ogólnie rzecz mówiąc, jak to przyzwoicie zorganizować, by miało ręce i nogi?
Go to the top of the page
+Quote Post
ber32
post
Post #10





Grupa: Zarejestrowani
Postów: 332
Pomógł: 22
Dołączył: 6.07.2010

Ostrzeżenie: (0%)
-----


Widzę, że lektury nie odrobiłeś. Tu przykład z manuala skopiowany, żebyś nie musiał ciężko szukać w taki upał (IMG:style_emoticons/default/oneeyedsmiley02.png)
  1. <?php
  2. /* Create a PDOStatement object */
  3. $stmt = $dbh->prepare('SELECT foo FROM bar');
  4.  
  5. /* Create a second PDOStatement object */
  6. $otherStmt = $dbh->prepare('SELECT foobaz FROM foobar');
  7.  
  8. /* Execute the first statement */
  9. $stmt->execute();
  10.  
  11. /* Fetch only the first row from the results */
  12. $stmt->fetch();
  13.  
  14. /* The following call to closeCursor() may be required by some drivers */
  15. $stmt->closeCursor();
  16.  
  17. /* Now we can execute the second statement */
  18. $otherStmt->execute();

teraz już chyba wiesz, kiedy go stosować ?
Go to the top of the page
+Quote Post
SlimShady
post
Post #11





Grupa: Zarejestrowani
Postów: 29
Pomógł: 0
Dołączył: 11.05.2013

Ostrzeżenie: (0%)
-----


u lala, dziękuje (IMG:style_emoticons/default/biggrin.gif) i naprawdę tylko wtedy mam go stosować? - głupie pytanie (IMG:style_emoticons/default/tongue.gif)

Ten post edytował SlimShady 7.07.2013, 17:03:31
Go to the top of the page
+Quote Post
ber32
post
Post #12





Grupa: Zarejestrowani
Postów: 332
Pomógł: 22
Dołączył: 6.07.2010

Ostrzeżenie: (0%)
-----


Nie
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 28.09.2025 - 22:52