我构建了这个类来使用PDO,使SQL查询“更容易”而不用担心。
以下是我的想法
谢谢
`
class Db
{
private static $_instance = NULL;
private function __construct() {
// can not call me
}
private function __clone() {
// no!
}
public static function getInstance() {
if (!self::$_instance)
{
try {
self::$_instance = new PDO('mysql:host=' . CONFIG_MYSQL_SERVER . ';dbname=' . CONFIG_MYSQL_DATABASE, CONFIG_MYSQL_USERNAME, CONFIG_MYSQL_PASSWORD);;
self::$_instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
trigger_error($e->getMessage());
}
}
return self::$_instance;
}
public static function query($query /*string*/, $bindings = NULL)
{
$queryPortion = substr($query,0, 6);
try {
if ($bindings) {
$prepared = self::getInstance()->prepare($query);
foreach($bindings as $binding=>$data) { // defaults to string
if (!is_array($data)) {
$prepared->bindParam($binding, $data);
} else {
switch(count($data)) {
case 1:
$prepared->bindParam($binding, $data['value']);
break;
case 2:
$prepared->bindParam($binding, $data['value'], $data['dataType']);
break;
case 3:
$prepared->bindParam($binding, $data['value'], $data['dataType'], (int)$data['length']);
break;
default:
trigger_error('An error has occured with the prepared statement bindings.');
return false;
break;
}
}
}
$prepared->execute();
return $prepared->fetchAll(PDO::FETCH_ASSOC);
} else if (String::match($queryPortion, 'select')) { // if this is a select query
$rows = self::getInstance()->query($query);
return $rows->fetchAll(PDO::FETCH_ASSOC);
} else {
return self::getInstance()->exec($query);
}
}
catch(PDOException $e)
{
trigger_error($e->getMessage());
}
}
public static function getLastInsertId()
{
try {
self::getInstance()->lastInsertId();
}
catch(PDOException $e)
{
trigger_error($e->getMessage());
}
}
public static function disconnect()
{
// kill PDO object
self::$_instance = NULL;
}
}
答案 0 :(得分:5)
它并不坏,因为据说它可能对小应用程序有所帮助,尽管它主要是对另一个抽象的非常薄的抽象。它并没有带来很多其他功能。
您可能需要考虑的事项,其中包括:
trigger_error
和set_exception_handler
,直到异常更为广泛,但它绝对更清晰,更具未来性。query()
方法使用存储过程might return a result set。;;
行末尾有两个分号(new PDO
)。话虽这么说,我认为你的查询方法不是太大,而且目前其他地方也无法回忆起来。虽然只要看到可以从另一个函数调用的两行或三行,就将其拆分。这是DRY的好方法。
答案 1 :(得分:2)
是和否。
这是一个简单的快速和脏应用程序的良好代码。
当您在更复杂的结构化应用程序中使用它时会出现问题。 错误处理将根据您正在执行的sql而有所不同。
此外,任何严重错误都会显示为“999行问题”类型错误 999在你的超级常规程序中,你将难以追溯它 到特定的sql请求。
说过我在小项目上一直这样做。
答案 2 :(得分:2)
这是我使用过的(只需用$ GLOBALS ['db_conf']或其他东西替换对Zzz_Config的引用):
/**
* Extended PDO with databse connection (instance) storage by name.
*/
class Zzz_Db extends PDO
{
/**
* Named connection instances.
*
* @var array
*/
static private $_instances;
/**
* Retrieves (or instantiates) a connection by name.
*
* @param string $name Connection name (config item key).
* @return Zzz_Db Named connection.
*/
static public function getInstance($name = null)
{
$name = $name === null ? 'db' : "db.$name";
if (!isset(self::$_instances[$name])) {
if (!$config = Zzz_Config::get($name)) {
throw new RuntimeException("No such database config item: $name");
}
if (!isset($config['dsn'])) {
if (!isset($config['database'])) {
throw new RuntimeException('Invalid db config');
}
$config['dsn'] = sprintf('%s:host=%s;dbname=%s',
isset($config['adapter']) ? $config['adapter'] : 'mysql',
isset($config['host']) ? $config['host'] : 'localhost',
$config['database']);
}
$db = self::$_instances[$name] = new self(
$config['dsn'],
isset($config['username']) ? $config['username'] : null,
isset($config['password']) ? $config['password'] : null);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'Zzz_Db_Statement');
if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$db->exec('SET CHARACTER SET utf8');
}
}
return self::$_instances[$name];
}
}
用法应该是:
$db = Zzz_Db::getInstance(); // or Zzz_Db::getInstance('some_named_db')
$stmt = $db->prepare('SELECT ...
目标是将db配置保存在* .ini文件中(可由非编码器编辑)。
答案 3 :(得分:1)
我走了另一条路,创建了一个扩展PDO的类,其中包含prepare()
/ execute()
周围的一堆包装函数,它比内置函数更好(尽管这有点主观。 ..)。
另一件事:您应该将PDO::ATTR_EMULATE_PREPARES
设置为false
,除非您使用的是旧版本的mysql(< = 4.0)。它默认为true
,这是一个非常令人头痛的问题,导致事情以不明显的方式破坏......我猜这是你在bindParam()
首先得到一个巨大包装的原因
答案 4 :(得分:0)
要回答你的问题,如果这是一个好的代码,请问自己:
与直接使用PDO相比,我的代码增值是多少?
如果您找到了一个好的答案,请继续使用您的代码。如果没有,我会坚持使用PDO。
另外,请尝试考虑实现Zend Framework的DB类,它自己运行并支持PDO。