2013-12-13 144 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