Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Moja klasa do obsługi MySQL pod PDO
Forum PHP.pl > Forum > Przedszkole
Apocalyptiq
Witam!

Ostatnio przeszedłem z AdoDB na PDO. Napisałem (z pomocą tutejszych forumowiczów 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ć smile.gif

Może macie jakieś swoje, z których korzystacie? Albo jakieś gotowe klasy, które można pobrać z neta?
nospor
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 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.
dr_bonzo
A co jak mam inna nazwe klasy, usera, hasla?
nospor
kolejna podstawa:
  1. <?php
  2. $db->sql("SELECT * FROM users WHERE cos=?","row",0);
  3. ?>

I jak myslisz, zbinduje mi to 0 czy nie?
Apocalyptiq
No nie zbinduje :/

A znasz może jakąś gotową prostą bibliotekę (klasę) do obsługi PDO? smile.gif Też słyszałem o Mysqli, ale jak czytałem - PDO jest lepsze.
nospor
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 winksmiley.jpg
Apocalyptiq
Dzięki nospor za wskazówki, i to z bindem null 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?
nospor
jedna funkcja, ktora robi wszystko to "ble" 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
Apocalyptiq
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 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ć?
dr_bonzo
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.
Apocalyptiq
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ż.
nospor
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
erix
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? tongue.gif
Apocalyptiq
a jak sie wypluwa wyjątki? smile.gif
Apocalyptiq
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.
megawebmaster
Bo wyjątki się wypluwa wtedy, kiedy nie może dalej działać kod. Czyli w sytuacji wyjątkowej 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.
Apocalyptiq
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 winksmiley.jpg
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.