Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP]Moja klasa do obsługi MySQL pod PDO, proszę o oceny i pomysły co do zmian :)
Apocalyptiq
post
Post #1





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


Witam!

Ostatnio przeszedłem z AdoDB na PDO. Napisałem (z pomocą tutejszych forumowiczów (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) ) taką klasę:

Kod
<?php class Database{
     protected $db;
     public function __construct(){
         $this->db=new Pdo('mysql:host=localhost;dbname=siatka','root','jo');
         $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
     }
     public function sql($query,$return='exec',$binds=null){
         $sql=$this->db->prepare($query);
         if($binds!=null){
             if(is_array($binds)){
                 foreach($binds as $n => $bind)
                     $sql->bindValue(($n+1), $bind);
             } else
                 $sql->bindValue(1, $binds);
         }
         if($sql->execute()){
             # włączenie tablic jedynie asocjacyjnych
             # if($return!='exec') $sql->setFetchMode(PDO::FETCH_ASSOC);
             switch($return){
                 case 'all':
                     return $sql->fetchAll();
                     break;
                 case 'one':
                     return $sql->fetchColumn();
                     break;
                 case 'row':
                     return $sql->fetch();
                     break;
                 case 'id':
                     return $this->db->lastInsertId();
                     break;
             }
         } else
             return false;
     }
}
$db=new Database();?>

No i teraz, jeżeli np. z tabeli users chcę pobrać wiersz, gdzie login = $_POST['login'], piszę takie coś:
Kod
<?php $db->sql("SELECT * FROM users WHERE login=?","row",$_POST['login']);?>
. Dla rodzaju returnowania exec - nic nie jest zwracane. Służy to tylko do wykonywania działań na bazie: insert, update, delete.

Zamierzałem jakoś zoptymalizować tą klase - tj. rozbić jakoś rodzaj returnowania, zrobić osobne funkcje na returnowanie wiersza, wszystkiego, rekordu... Wtedy aby pobrać wiesz, napisalibyśmy np. $db->getRow("SELECT * FROM users WHERE id=1"). Proszę o jakieś pomysły jak tą klasę nieco zoptymalizować (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Może macie jakieś swoje, z których korzystacie? Albo jakieś gotowe klasy, które można pobrać z neta?

Ten post edytował nospor 17.11.2008, 13:23:37
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 17)
nospor
post
Post #2





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




1) uzyj poprawnego bbcode
2) Przenosze. Z mysql to ma sredni związek, na oceny tez sie nie nadaje, pozostaje wiec przedszkole


źle:
- robie update - skad mam wiedziec czy sie powiodl czy nie? z twojej klasy to nie wynika.
- Chce pobrac pokolei kazdy rekord i poddac obróbce. zeby to zrobic z Twoją klasą muszę pobrac wszystkie rekordy i na nowo ponich iterowac.
- wiele innych (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

dobrze:
-hmmm, nic nie znalazlem

edit:
twoja klasa to jedna funkcja, która z twojego punktu widzenia ma robic wszystko, a z mojego punktu widzenia nie robi nic, czego da sie uzywac w normalnych projektach.
Upchnięcie wszystkiego w jedną funkcję jest złym pomysłem.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #3





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

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


A co jak mam inna nazwe klasy, usera, hasla?
Go to the top of the page
+Quote Post
nospor
post
Post #4





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




kolejna podstawa:
  1. <?php
  2. $db->sql("SELECT * FROM users WHERE cos=?","row",0);
  3. ?>

I jak myslisz, zbinduje mi to 0 czy nie?
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #5





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


No nie zbinduje :/

A znasz może jakąś gotową prostą bibliotekę (klasę) do obsługi PDO? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Też słyszałem o Mysqli, ale jak czytałem - PDO jest lepsze.
Go to the top of the page
+Quote Post
nospor
post
Post #6





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
No nie zbinduje

Zamiast $binds!=null
daj: $binds!==null
i juz zbinduje

Cytat
A znasz może jakąś gotową prostą bibliotekę (klasę) do obsługi PDO

PDO samo w sobie jest klasą i nadaje sie do uzywania.
Jedyna nakładkę jaką widziałem była napisana przez Zyx ale nie jest juz rozwijana bo ktos wydal podobno lepszą (o czym sam pisał Zyx).
Ja używam własnej, ale mocno zintegrowanej z moim systemem, wiec nic tu po niej (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #7





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


Dzięki nospor za wskazówki, i to z bindem null (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Jeszcze pytanie co do tego ustalania returnowania - lepiej zostawić tak jak teraz, czy może napisać te osobne funkcje (getRow, getAll, getOne, exec)? Np. w AdoDB właśnie to tak było zorganizowane, ale nie wiem jak wydajniej - niby mniej argumentów w funkcji, ale za to więcej funkcji. Dla wszystkich tych funkcji początek byłby ten sam - bindowanie ewentualnych zmiennych. Jak tego dokonać - napisać główną klasę, która binduje zmienne, i te 4 klasy, które dziedziczą tą z bindowaniem i robią swoje, tak?
Go to the top of the page
+Quote Post
nospor
post
Post #8





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




jedna funkcja, ktora robi wszystko to "ble" (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Ma być kilka metod. Mogą one korzystać z jakiejs metody wspolnej, ktora bedzie robila czesto powtarzany kod.
Twoja klasa nie moze mnie ograniczac w funkcjach PDO, a w tej chwili ogranicza i to bardzo.

Cytat
Jak tego dokonać - napisać główną klasę, która binduje zmienne, i te 4 klasy,

Klasa jedna, z paroma metodami
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #9





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


A jak ustawić, aby te metody korzystały z tej jednej głównej metody? W klasach to się robi przez extended, a w metodach? Po prostu coś takiego:
Kod
class Database{
    protected $db;
    public function __construct(){
        $this->db=new Pdo('mysql:host=localhost;dbname=siatka','root','jo');
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    public function exec($query, $binds=null){
        $sql=$this->db->prepare($query);
        if($binds!==null){
            if(is_array($binds)){
                foreach($binds as $n => $bind)
                $sql->bindValue($n+1,$bind);
            } else
                $sql->bindValue(1,$binds);
        }
        if($sql->execute()) return $sql; else return false;
    }
    public function getAll($query, $binds=null){
        $sql=$this->exec($query,$binds);
        if($sql!==false) return $sql->fetchAll();
    }
    public function getRow($query, $binds=null){
        $sql=$this->exec($query,$binds);
        if($sql!==false) return $sql->fetch();
    }
    public function getOne($query, $binds=null){
        $sql=$this->exec($query,$binds);
        if($sql!==false) return $sql->fetchColumn();
    }
    public function insertId($query, $binds=null){
        $sql=$this->exec($query,$binds);
        if($sql!==false) return $this->db->lastInsertId();
    }
}
$db=new Database();


Dzięki nospor za rady! ;-)
PS. Jakby w tej klasie jeszcze coś było nie tak, prosze napisz (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) np. czy przy każdej z tych pomniejszych metod trzeba dodawać $sql=$this->sql($query,$binds);? nie można tego jakoś skrócić?

Ten post edytował Apocalyptiq 17.11.2008, 16:37:53
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #10





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

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


Cytat
czy przy każdej z tych pomniejszych metod trzeba dodawać $sql=$this->sql($query,$binds);? nie można tego jakoś skrócić?

Eh, clzowieku, pomysl troche. Mozesz ta linijke wyrzucic, tylko ze kod juz nie bedzie ci dzialal.

i 2. zajrzyj do mojej poprzedniej uwagi.
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #11





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


No ale tą klasę piszę do działania na jednej bazie, na jednej stronie, user i hasło będzie zawsze takie same. A nazwa klasy będzie zawsze taka sama przecież.
Go to the top of the page
+Quote Post
nospor
post
Post #12





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




no ale powiedzmy ze te klase dasz koledze.
On bedzie te dane mial inne. No i teraz zmieni te dane w tej klasie.
ALe ty poprawisz troche klase, dasz mu nowy kod i on znowu straci swoje ustawienia - bedzie musial na nowo wprowadzac.
Teraz znowu zmieniasz kod, dajesz mu nowy i tak w kolko macieja.

A jak bedziesz do konstruktora przekazywal parametry połączenia to kolega ustawi je przy tworzenia obiektu i kazda twoja nowa poprawka nie nadpisze mu jego ustawien
Go to the top of the page
+Quote Post
erix
post
Post #13





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Cytat
PS. Jakby w tej klasie jeszcze coś było nie tak, prosze napisz

A dlaczego np. nie użyjesz wypluwania wyjątków, tylko zwracasz false? Używasz MacOS-a, czy co? (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)

Ten post edytował erix 17.11.2008, 17:07:40
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #14





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


a jak sie wypluwa wyjątki? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
erix
post
Post #15





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




exceptions" title="Zobacz w manualu PHP" target="_manual
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #16





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


A jak to wsadzić do takiej bazy? W wikibooks widziałem zastosowanie tego exception, ale tam całe połączenie z bazą, zapytanie itp. bierze się w klamrę - a tu wszystko mam osobno, więc jak to zrobić?
Kod
    public function exec($query, $binds=null){
$sql=$this->db->prepare($query);
if($binds!==null){
if(is_array($binds)){
foreach($binds as $n => $bind)
$sql->bindValue($n+1,$bind);
} else
$sql->bindValue(1,$binds);
}
try{
$sql->execute();
}
catch(PDOException $e)
{
echo 'Wystapil blad biblioteki PDO: ' . $e->getMessage();
}
?
I do czego w ogóle służy to wypluwanie wyjątków? Teraz, jak coś jest nie tak, po prostu wywalany mam błąd, tylko że dalsza część kodu wtedy nie jest wykonywana.

Ten post edytował Apocalyptiq 17.11.2008, 20:09:41
Go to the top of the page
+Quote Post
megawebmaster
post
Post #17





Grupa: Zarejestrowani
Postów: 143
Pomógł: 17
Dołączył: 8.11.2008
Skąd: Libiąż

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


Bo wyjątki się wypluwa wtedy, kiedy nie może dalej działać kod. Czyli w sytuacji wyjątkowej (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Przy reszcie możesz np. zwracać false, tylko musisz sobie sprawdzać czy wszystko wykonało się prawidłowo. Poza tym - chyba cały kod związany z PDO ma być objęty przez TRY, bo każda jego funkcja wyrzuca wyjątek przy jakimś poważnym błędzie.
Go to the top of the page
+Quote Post
Apocalyptiq
post
Post #18





Grupa: Zarejestrowani
Postów: 230
Pomógł: 3
Dołączył: 8.01.2008

Ostrzeżenie: (10%)
X----


Zmodyfikowałem klasę co do wyjątków:

Kod
<?php class Database{
     protected $db;
     public function __construct(){
         $this->db=new Pdo('mysql:host=localhost;dbname=siatka','root','jo');
         $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
     }
     public function exec($query, $binds=null){
         try{
             $sql=$this->db->prepare($query);
             if($binds!==null){
                 if(is_array($binds)){
                     foreach($binds as $n => $bind)
                     $sql->bindValue($n+1,$bind);
                 } else
                     $sql->bindValue(1,$binds);
             }
             $sql->execute();
         } catch(PDOException $e){
             $_SESSION['mesg']='Wystapil bląd biblioteki PDO: '.$e->getMessage();
         }
         return $sql;
     }
     public function getAll($query, $binds=null){
         $sql=$this->exec($query,$binds);
         return $sql->fetchAll();
     }
     public function getRow($query, $binds=null){
         $sql=$this->exec($query,$binds);
         return $sql->fetch();
     }
     public function getOne($query, $binds=null){
         $sql=$this->exec($query,$binds);
         return $sql->fetchColumn();
     }
     public function insertId($query, $binds=null){
         $sql=$this->exec($query,$binds);
         return $this->db->lastInsertId();
     }
}
$db=new Database();?>


W $_SESSION["mesg"] przechowuje tymczasowe komunikaty, które później ładowane są na stronę.
Nic nie szkodzi, że returnuje $sql poza try{}catch{}? Bo wsadzając return $sql w try{}, funkcja mi nic nie zwróci. Jeżeli jest błąd, to execute() wywali false, ale jeżeli go drugi raz wywołam, to chyba drugi raz się wykona, tak? Jakbym dał tak:
Kod
        try{
             $sql=$this->db->prepare($query);
             if($binds!==null){
                 if(is_array($binds)){
                     foreach($binds as $n => $bind)
                     $sql->bindValue($n+1,$bind);
                 } else
                     $sql->bindValue(1,$binds);
             }
             $sql->execute();
         } catch(PDOException $e){
             $_SESSION['mesg']='Wystapil bląd biblioteki PDO: '.$e->getMessage();
         }
         if($sql->execute()) return $sql;

To zapytanie $sql ponownie wykona się na bazie?

[EDIT]

Co do podawania danych do połączenia, tak zmieniłem początek klasy Database:
Kod
class Database{
    protected $db;
    public function connect($engine,$host,$user,$pwd,$dbname){
        $this->db=new Pdo($engine.':host='.$host.';dbname='.$dbname,$user,$pwd);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
...

I teraz na początku index'u wypisujemy takie coś:
Kod
<?php #wrzucenie klasy Database
require_once 'inc/db.php';
$db=new Database();
$db->connect('mysql','localhost','root','haslo','nasza_baza');?>

I działa, dzięki za sugestie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Ten post edytował Apocalyptiq 18.11.2008, 12:12:47
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: 22.08.2025 - 14:19