这包装为一项旨在'好的代码?是否有任何潜在的问题?
-
03-07-2019 - |
题
我建立了这类工作与公设辩护人,使SQL queries'更容易',而不用担心。
这里是我的想法
- 应该更像类DB延伸公设辩护?
- 是的查询方法太大?它应该被分成私人的方法,这是所谓的..这就是被称为 松散耦合?
- 是我的方式用于检测选择的查询太丑陋为它自己很好吗?
- 什么其他的问题是显而易见?因为我种学习如我去,我肯定我有可能忽略了一个很大的潜力问题。
谢谢你
`
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;
}
}
解决方案
这不是坏的,因为它已经说它可能有助于小型应用程序虽然它主要是一个非常薄抽象的另一个抽象概念。它不带来了大量的其他功能。
有些东西你可能想要考虑,除其他事项外:
- 因为这是PHP5码,用 例外情况 而不是的
trigger_error
和set_exception_handler
如果需要,直到的例外是更为普遍,但它是绝对清洁和更面向未来。 - 你使用一个单一实例,这不是一件坏事一定但在这种情况下,例如,一个缺点将是,你将仅仅能够处理一个连接到一个数据库。
- 我不知道如果你使用的存储程序,但是存储的过程 可能返回的结果设定 通过
query()
法。 - 你有两分号(
;;
)结束时的你new PDO
线。
这就是说,我不认为你的查询方法是太大而没有太多可以回顾从其他地方在那里的时刻。但只要你看到两个或三个线,可以从另一个功能分割的。这是一个很好的方式 干.
其他提示
是的,没有。
这是很好的编码于一个简单快速的和肮脏的应用程序。
问题是当你使用这一更为复杂的结构化应用程序。其中的错误处理,将取决于其sql你是执行。
还有任何严重的错误,将显示为"问题的在线999"类型的错误。 在999是你的超级强行将难以追踪它找回来 一个特别sql请求。
具有说我做这样的事情自己所有的时间上的小型项目。
这里就是我的使用(只更换引用Zzz_Config与$GLOBALS['db_conf']或类):
/**
* 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 ...
我们的目标是保持数据库的配置在一个*.ini文件(编辑通过一个非编码器).
我去的其他方式,并提出了类延伸的公设辩护人与一堆包功能的周围 prepare()
/execute()
, ,这是更漂亮比建立在功能(虽然这一点主观的...).
另一件事情:你应该设置 PDO::ATTR_EMULATE_PREPARES
要 false
除非你使用一个真正的老版本的mysql(<=4.0).它默认 true
, ,这是一个巨大的头痛并导致东西打破在晦涩的方式...我猜是因为你已经有了一个巨大的包装 bindParam()
在第一位。
来回答你的问题,如果它是一个很好的代码或不是,问问自己:
有什么增加的价值我的代码相比,使用一项旨在直接?
如果你找一个很好的答案,去使用你的代码。如果没有,我会坚持公设辩护人.
还尽量考虑到执行 Zend框架's DB级,它适用于其自身,并支持公设辩护人.