Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] PDO singelton
Forum PHP.pl > Forum > Przedszkole
Pol78
Cześć, mam problem z własną klasą do obsługi bazy.

Tymczasowo mam tylko samo połączenie, ale docelowo chciałbym w tej klasie zamieścić uniwersalne metody do wykonywania select'ów / update'ów / etc.

Kod mojej klasy:

  1. <?php
  2. class DB
  3. {
  4.    private static $instance;
  5.  
  6.    private function __construct()
  7.    {
  8.        $dsn_user = 'xxx';
  9.        $dsn_pass = 'yyy';
  10.        $dsn_host = 'zzz';
  11.        $dsn_base = 'www';
  12.  
  13.        try
  14.        {
  15.            self::$instance = new PDO ("mysql:host=" . $dsn_host . ";dbname=" . $dsn_base . ";port=3306", $dsn_user, $dsn_pass);
  16.            self::$instance->exec("SET NAMES UTF8");
  17.        }
  18.        catch (PDOException $e)
  19.        {
  20.            echo "DB error (" . $e->getMessage() . ")";
  21.            exit;
  22.        }
  23.    }
  24.  
  25.    private function __clone() {}
  26.  
  27.    public static function getInstance()
  28.    {
  29.        if (self::$instance === null)
  30.        {
  31.            self::$instance = new self();
  32.        }
  33.        return self::$instance;
  34.    }
  35. }
  36. ?>



I teraz jak próbuje jej użyć:

  1. <?php
  2. require_once( dirname(__FILE__) . '/../class/DB.class.php' );
  3.  
  4.    $db = DB::getInstance();
  5.  
  6.    $r = $db->query("select * from Table");
  7. ?>


to dostaje komunikat: Fatal error: Call to undefined method DB::query().

Może mi ktoś wskazać gdzie popełniam błąd? Z góry dzięki za pomoc!
wookieb
Jak już to rozszerz sobie PDO

Kod
class DB extends PDO

i wtedy dodaj tam singletona.
drPayton
Cytat
Call to undefined method DB::query()


A co niejasnego jest w tym komunikacie? blinksmiley.gif


@up: Ano
Pol78
Cytat(wookieb @ 16.03.2009, 00:22:51 ) *
Jak już to rozszerz sobie PDO

Kod
class DB extends PDO

i wtedy dodaj tam singletona.


No tak, ale w takim przypadku (class DB extends PDO) nie mogę zablokować konstruktora (private function __construct() {}) bo krzyczy mi błędem (Access level to DB::__construct() must be public (as in class PDO)).
Jak w takim przypadku zabezpieczyć klasę przed możliwością tworzenia obiektu?
Mephistofeles
A po co blokować konstruktor? Dopóki tylko ty korzystasz z tego kodu to nie ma takiej potrzeby.
Albo drugie wyjście, zamiast new self daj new PDO(...). Ale to już będzie mniej zgodne z wzorcem.
Pol78
Tak się dziś cały dzień zastanawiam nad powyższym rozwiązaniem i wymyśliłem taką mieszankę singeltona i klasy statycznej (o ile można tak to nazwać smile.gif

  1. <?php
  2. class DB
  3. {
  4.    private static $instance;
  5.  
  6.    private function __construct() {}
  7.    private function __clone() {}
  8.  
  9.    private static function getInstance()
  10.    {
  11.        if (self::$instance === null)
  12.        {
  13.            try
  14.              {
  15.                  self::$instance = new PDO ("mysql:host=aaa;dbname=bbb;port=3306", "ccc", "ddd");
  16.                  self::$instance->exec("SET NAMES UTF8");
  17.              }
  18.              catch (PDOException $e)
  19.              {
  20.                  echo "DB error (" . $e->getMessage() . ")";
  21.                  exit;
  22.              }
  23.        }
  24.        return self::$instance;
  25.    }
  26.  
  27.  
  28.    public function query($_sql)
  29.    {
  30.        self::getInstance();
  31.        $_r = self::$instance->prepare($_sql);
  32.        if ( !$_r->execute() )
  33.        {
  34.            echo "DB error (" . $_r->errorInfo() . ")";
  35.            exit;
  36.        }
  37.        return $_r->fetchAll();
  38.    }
  39. }
  40. ?>


I potem wystarczy tylko tyle do użycia:

  1. <?php
  2. $r = DB::query("select * from Table");
  3. ?>


Co sądzicie o takim rozwiązaniu? Ma rację bytu czy raczej przekombinowane?
Fifi209
Ja bym powiedział tak:

Albo klasa statyczna albo nie.

Jeżeli masz metody "niestatyczne" to singleton'a robisz tak:
  1. <?php
  2. private __construct() {
  3. // konstruktor
  4. }
  5.  
  6. public function sing() {
  7. static $handle;
  8. if (!isset($handle)) {
  9. $handle = new nazwaklasy();
  10. }
  11. return $handle
  12. }
  13. ?>


i tworzysz potem obiekt klasy
$test = nazwaklasy::sing();
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.