2013-12-13 185 views
1

我想開始使用PDO(從MySQL擴展切換),我想添加一些方法,但仍然具有整個PDO功能。我想實現這樣的功能:擴展PDO類

$db->getAll("SELECT * FROM table WHERE field1=:foo AND field2=:baz", array('foo'=>$foo, 'baz'=>$baz)); 

我認爲最好的辦法是延長PDO類,但在這種情況下,我不會有類的實例才能夠使用它裏面的類。任何想法?

+0

'class DB extends PDO {}'?然後你可以使用'$ this-> pdoMethod()'調用PDO方法。 – h2ooooooo

+0

我想到的一件事是,runkit_method_add()。我想不出任何其他方式來添加方法到一個類。 –

+4

不要擴展,但要創建一個包裝。 –

回答

4

我會建議反對擴展PDO,而是建立一個其他ORM的庫/包裝器。

我將構建您的示例代碼到一個簡單的類中進行解釋。

class MyDB 
{ 

    private $pdo; 

    public function __construct(PDO $pdo) 
    { 
     $this->pdo = $pdo; 
    } 

    public function getAll($query, array $params) 
    { 
     $statement = $this->pdo->prepare($query); 
     $statement->execute($params); 
     return $statement->fetchAll(); 
    } 

    public function getPdo() 
    { 
     return $this->pdo; 
    } 

    /** 
    * This is called if the method cannot be found. 
    * Pass it to PDO to handle. 
    * 
    * @param $name 
    * @param $arguments 
    */ 
    public function __call($name, $arguments) 
    { 
     return call_user_func(array($this->pdo, $name), $arguments) 
    } 

} 

如果你真的想直接訪問PDO,那麼我已經包含了一個神奇的方法,但我不建議你採取這種路線。看到http://www.php.net/manual/en/language.oop5.magic.php

做這種東西對於學習來說很有趣,但是如果你想要一個嚴肅的ORM,那麼看看這個SO問題Good PHP ORM Library?並且研究你自己。

+0

或者有人可能會選擇使用已有的庫中的一個:) – KingCrunch

+0

是或那,我更喜歡! – SamV

+0

很好的例子:如果可能,選擇繼承的組合 – douwe

-5

一個單例如:

class DB 
{ 
    protected static $instance = null; 

    final private function __construct() {} 
    final private function __clone() {} 

    public static function instance() 
    { 
     if (self::$instance === null) 
     { 
      $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME; 
      self::$instance = new PDO($dsn, DB_USER, DB_PASS); 
      self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 
     return self::$instance; 
    } 
    public static function __callStatic($method, $args) { 
     return call_user_func_array(array(self::instance(), $method), $args); 
    } 

    public static function getAll($sql, $data = NULL, $mode = PDO::FETCH_ASSOC) 
    { 
     $stmt = self::instance()->prepare($sql); 
     $stmt->execute($data); 
     return $stmt->fetchAll($mode); 
    } 
} 

$sql = "SELECT * FROM table WHERE field1=:foo AND field2=:baz"; 
$data = DB::getAll($sql, array('foo'=>$foo, 'baz'=>$baz)); 
+1

辛格爾頓是一個反模式。只是說...當涉及數據庫連接時,「但在某些情況下......」這個說法是無效的,你可能需要也可能不需要超過一次;) – KingCrunch

+0

這讓我想知道,爲什麼Laravel使用單身人士與數據庫交互。可能是因爲有些人認爲不是那種反模式。 –

+1

「Sombody使用它,它必須是最佳實踐」?你在開玩笑嗎? – KingCrunch

0

你在你的項目中深就在這裏是你的一個建議。用ORM庫做。

比如我做的,你需要與ORM庫(在本例中名爲db.php中)一樣的東西是這樣的:

$database->path->to->table->handler->load (\db\by('field1',$value1)->by('field2',$field2)); 

用的ORM的複雜的事情是,他們需要類定義一起工作表和許多PHP開發人員害怕他們的數據對象的類定義。對於上面的例子中工作,你應該需要一個類定義是這樣的:

namespace \path\to; 
class table 
{ 
    public $field1; 
    public $field2; 
} 

和數據庫初始化在db.php中ORM庫的情況是這樣的:

$database = new \db\database ('mysql:host=127.0.0.1', 'test_db', 'root', '1234'); 

和類連接到數據庫對象處理這樣的:

$database->add ('\path\to\table'); 

另外許多的ORM有一個神奇的方法讓您根據您的類定義自動創建或生成表格,爲examp樂db.php中(http://dbphp.net)方法:

$database->update(); 

將在您的實際MySQL數據庫創建path_to_table表2場Field 1和域2。

我不確定爲什麼人們應該害怕PHP開發中的ORM,他們讓每個人都變得更輕鬆,並且在您從事大型項目時不會讓自己的代碼感到困惑。

我相信有時候這個答案會爲將來的痛苦至少救一個人。

:D