php单例数据库连接,这个代码是不好的做法?
我想创建一个简单的使用单例类来连接到mysql数据库和做的查询,代码工作正常,我没有任何问题,但因为我是新来OOP我想知道这是否是不好的做法。php单例数据库连接,这个代码是不好的做法?
这里的类
class Database {
private $databaseName = 'dbname';
private $host = 'localhost';
private $user = 'user';
private $password = 'pass';
private static $instance; //store the single instance of the database
private function __construct(){
//This will load only once regardless of how many times the class is called
$connection = mysql_connect($this->host, $this->user, $this->password) or die (mysql_error());
$db = mysql_select_db($this->databaseName, $connection) or die(mysql_error());
echo 'DB initiated<br>';
}
//this function makes sure there's only 1 instance of the Database class
public static function getInstance(){
if(!self::$instance){
self::$instance = new Database();
}
return self::$instance;
}
public function connect() {
//db connection
}
public function query($query) {
//queries
$sql = mysql_query($query) or die(mysql_error());
return $sql;
}
public function numrows($query) {
//count number of rows
$sql = $this->query($query);
return mysql_num_rows($sql);
}
}
//Intantiate the class
$database = Database::getInstance();
,当我想使用这个类,我会做:
$query = "SELECT * FROM registrations";
echo $database->numrows($query);
$sql = $database->query($query);
单身人士是坏消息。
- 它们将全局状态引入程序。大多数程序员应该熟悉为什么全局状态不好。
- 它们引入了单身人士和任何使用它的类之间的紧密耦合。这意味着你不能重用有问题的类而不重用单例。
- 他们进行单元测试的类依赖于单身问题,因为你不能轻易地用模拟替换单身。
- 他们鼓励类尝试解决自己的依赖关系的编码风格。这很糟糕,因为它可能会降低该类的依赖关系的清晰度。
- PHP有一个Share Nothing架构,这意味着PHP单身人士根本不是单身人士,任何时候都可能有多个实例存在(每个开放请求一个)。
- 如果您在某个日期后突然发现您确实需要多个由单例提供的资源,会发生什么情况?这是比你想象的更常见的情况
你最好看看dependency-injection,因为它可以解决上述问题。
你能否提供一些关于'dependency-injection'的好文章,以及为什么“Registry for database”是个坏主意? (我知道我可以谷歌它,但确认质量和来自可靠来源的东西) – Vyktor 2012-02-10 12:29:09
注册表在大多数方面(全局状态,鼓励类解决依赖关系等)都像单身人士。至于DI,如果你是谷歌,那么就有很多文章,就像你说的那样。 :)我相信Symfony框架的文档包含了一个很好的关于DI在PHP上下文中的讨论。 – GordonM 2012-02-10 12:34:00
自动装载机类怎么样,(我的答案的扩展名)'get($ connName)'会自动使用'configs/$ connName.ini'初始化连接?我知道你应该提供带有“Controller”连接的“Model”,模型不应该像DBs :: get('export')那样做,但是指定默认连接有什么问题? – Vyktor 2012-02-10 12:39:00
这种模式将被罚款,因为单只适用于当前用户会话。这个决定实际上取决于你的优先权。如果你想为用户提供更快的性能,那么你希望允许每个用户有更多的数据库连接,但是如果你想限制你的数据库被攻击的难度,那么这个单例会给你一个很好的中间路线。
单身汉是个坏消息。他们应该避免。 – GordonM 2012-02-10 12:25:25
@GordonM,非常真实。你的忠告是更审慎的长期解决方案。 – davidethell 2012-02-10 16:32:58
我认为一个单身人士对于连接管理员来说可以,但对于连接本身不是。
你永远不知道什么时候需要为开发的特定部分建立额外的连接。假设您突然需要添加与远程数据库的同步。
连接管理器(可以管理多个连接)可以是单例。连接本身;没有。
你的连接管理器还应该能够加载“驱动程序”,这样你就可以实现一个MySQL连接,当你需要msSQL,sqLite或其他任何东西时,你可以添加所需的驱动程序。
我会说这取决于你使用这个类的方式。如果每次要使用数据库时都致电Database::getInstance()
,从面向对象的角度来看,这是不好的,因为它会影响可测试性。如果你只做了一次,然后将实例注入需要使用数据库的对象,那么使用singleton并不坏(但仍然不必要)。
我建议你看一下依赖注入的概念: http://misko.hevery.com/2008/11/11/clean-code-talks-dependency-injection/或 http://fabien.potencier.org/article/11/what-is-dependency-injection
我听说在PHP Singleton设计模式的唯一积极的论据是从谁实施的组合,辛格尔顿数据库连接的开发与一个Memcached对象。我实际上没有机会看看代码和性能,但他能够提出一个连贯的论点。我个人并不认为Singleton设计模式与PHP非常相关,无论如何,这在很大程度上都是无状态的(正如在每个请求都会有单例之前所指出的那样)。
Singleton模式通常在数据库类,记录器,前端控制器或请求和响应对象中实现。 – diEcho 2012-02-10 12:05:09
我在这里看不到任何问题 – jere 2012-02-10 12:06:08
你可以看到有大量的db类。甚至可以查看codeigniter等框架以查看其db类的工作方式。 – 2012-02-10 12:06:34