php单例数据库连接,这个代码是不好的做法吗?
Posted
技术标签:
【中文标题】php单例数据库连接,这个代码是不好的做法吗?【英文标题】:php singleton database connection, is this code bad practice? 【发布时间】:2012-03-02 21:35:48 【问题描述】:我正在尝试创建一个简单的使用单例类来连接到 mysql 数据库并进行查询,代码工作正常,我没有遇到任何问题,但是由于我是 OOP 新手想知道这是否是不好的做法。
这是课程
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);
【问题讨论】:
单例模式通常在数据库类、记录器、前端控制器或请求和响应对象中实现。 我看不出有什么问题 您可以查看大量的 db 类。甚至查看诸如 codeigniter 之类的框架,看看它们的 db 类是如何工作的。 Who needs singletons? 的可能重复项 @diEcho 确实在***.com/a/4596323/208809 中进行了解释,并在其中给出了链接。你特别提到的那些可以很容易被butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne处理 【参考方案1】:这种模式会很好,因为单例只适用于当前用户会话。决定实际上取决于您的优先事项。如果您想为用户提供更快的性能,那么您希望每个用户允许更多的数据库连接,但如果您想限制数据库受到攻击的程度,那么单例可以为您提供一个很好的中间路径。
【讨论】:
单身人士是个坏消息。应该避免它们。 @GordonM,非常正确。您的建议是更谨慎的长期解决方案。【参考方案2】:我认为单例可以用于连接管理器,但不能用于连接本身。
您永远不知道何时需要为开发的特定部分建立额外的连接。假设您突然需要添加与远程数据库的同步。
连接管理器(可以管理多个连接)可以是单例的。连接本身;没有。
您的连接管理器还应该能够加载“驱动程序”,这样您就可以实例化 MySQL 连接,并且在您需要 msSQL、sqlite 或其他任何东西的那一天,您就可以添加所需的驱动程序。
【讨论】:
【参考方案3】:单身人士是个坏消息。
他们将全局状态引入程序。大多数程序员应该熟悉为什么全局状态不好。 它们在单例和使用它的任何类之间引入了紧密耦合。这意味着您不能在不重用单例的情况下重用有问题的类。 他们使依赖于单例的类的单元测试成为问题,因为您不能轻易地用模拟替换单例。 他们鼓励类尝试解决自己的依赖关系的编码风格。这很糟糕,因为它会降低类所具有的依赖项的清晰度。 php 具有无共享架构,这意味着 PHP 单例根本不是真正的单例,任何时候都可以有多个活动实例(每个打开请求一个)。 如果您后来突然发现您实际上需要多个由单例提供的资源,会发生什么情况?这是一种比您想象的更常见的情况您最好查看dependency-injection,因为它可以解决上述问题。
【讨论】:
您能否提供一些关于dependency-injection
的好文章以及为什么“数据库注册表”是个坏主意的解释? (我知道我可以用谷歌搜索它,但质量可靠且来源可靠)
注册中心在很多方面都类似于单例(全局状态、鼓励类解决依赖关系等)。至于 DI,如果你用谷歌搜索的话,那里有很多文章,就像你说的那样。 :) 我相信 Symfony 框架的文档包含了在 PHP 上下文中对 DI 的很好的讨论。
自动加载器类怎么样,(我的答案的扩展)get($connName)
将自动初始化与configs/$connName.ini
的连接?我知道您应该为“模型”提供来自“控制器”的连接,并且模型不应该像DBs::get('export')
那样做任何事情,但是指定默认连接有什么问题?【参考方案4】:
我听到的关于 PHP 中的 Singleton 设计模式的唯一积极论点是来自一位开发人员,他结合 Memcached 对象实现了 Singleton 数据库连接。我实际上并没有机会查看代码和性能,但他能够提出一个连贯的论点。
我个人不认为 Singleton 设计模式与 PHP 非常相关,无论如何它基本上是无状态的(正如在每个请求将有一个单例之前指出的那样)。
【讨论】:
以上是关于php单例数据库连接,这个代码是不好的做法吗?的主要内容,如果未能解决你的问题,请参考以下文章
在处理潜在的未定义变量时,在 PHP 中使用引用赋值是不好的做法吗?