在函数和多个脚本(PHP)中使用单例数据库类 - 最好使用方法

时间:2010-03-12 07:00:05

标签: php scope database-connection

我有一个单一的数据库连接,我得到了:

  

$ dbConnect = myDatabase :: getInstance();

这很容易。我的问题是在函数和类中使用此连接的最少修辞和合法方式是什么?将变量声明为global,将其传递给每个函数,和/或在每个函数中重新创建此变量似乎很愚蠢。还有另一个答案吗?

显然我是一个菜鸟,我可以通过10种不同的方式解决这个问题,其中没有一个对我很有吸引力。如果我可以在任何函数中访问$ dbConnect变量而不需要将其声明为全局或传入它,那将会容易得多。我知道我可以将变量添加到$ _SERVER数组中...是否有问题这样做?这似乎有点不合适。

另一个简单的问题:这样做是不好的做法:

  

$ result = myDatabase :: getInstance() - > query($ query);

直接来自一个函数?

4 个答案:

答案 0 :(得分:1)

其中一些将归结为品味。在工作中,我们还通过

获得ADODB连接句柄
$db = Registry :: getDB();

同样,您可以使用方法链来缩写部分代码:

$name = Registry :: getDB()->getOne(
    "SELECT name FROM user WHERE user_id = ?", $userId
);

使用注册表意味着您的调用代码具有对Registry类的具体依赖性。这使得测试代码变得困难(就我个人而言,这是我唯一一次使用注册表将我的头撞在墙上)

如果您希望代码add unit tests,则通常需要模拟数据库连接,这样每次运行测试套件时都不会操作数据库。

您仍然可以通过检查运行环境并使用模拟数据库抽象类配置注册表来解决此问题,但它不如依赖注入(DI)那么优雅。

我见过的DI和容器(对于PHP开发人员)的最佳解释是Fabien Potencier's Dependency Injection with PHP 5.3(从幻灯片9开始)。

你传递一个DI容器来代替一个注册表,它提供了一种优雅而简单的方法来获取依赖项的句柄(比如注册表),但它是灵活的,而且松散耦合,所以你可以在需要时模拟这些依赖项。

答案 1 :(得分:0)

我使用superglobal $ GLOBALS变量来保存我的数据库连接。令人惊奇。

你提到的所有好处,只要你是明智的并且使用哈希数组的唯一键并且只有一个入口函数来设置数据库连接并将其存储在阵列。

我现在就戴上耳塞,为所有关于使用全局变量的呻吟做好准备!

@Downvoters - 睡前阅读:

Are global variables bad?

https://stackoverflow.com/questions/357187/global-variables-when-are-they-acceptable

一些引用你的娱乐:

全局变量一直被许多程序员使用。我们现在只称他们为单身人士。” - DannySmurf

他们完全,从根本上说,绝对,令人难以置信,非常邪恶。” - Vinko Vrsalovic

这是克利特斯本人的最佳答案: Are global variables in PHP considered bad practice? If so, why?

答案 2 :(得分:0)

在整个应用程序中单例使用没有任何问题,有些人反对数据库攻击类的Singleton模式,因为将来很难处理多个连接。但在这种情况下,显示与Registry有几个相似之处的Singleton模式也应该有效。

我说你走在正确的轨道上!

答案 3 :(得分:0)

多年来我一直在处理这个问题。我会说将Singleton派生的对象添加到超级全局变量(如$ _GLOBAL或$ _SERVER)正在消除构建Singleton类的重点。

我认为最好的做法就是像你建议的那样访问它:

$result = Database_Class::singleton()->query('whatever');

我要添加的唯一内容是,在某些局部范围(如函数或方法)中,您希望多次使用Singleton对象,可能需要执行以下操作:

function func() {
  $db = Database_Class::singleton();
  $db->query('insert into whereever');
  $db->query('insert into whereever');
  $db->query('insert into whereever');
  $db->query('insert into whereever');
}