当前位置:  开发笔记 > 编程语言 > 正文

Global或Singleton用于数据库连接?

如何解决《Global或Singleton用于数据库连接?》经验,为你挑选了3个好方法。

在PHP中使用单例而不是全局的数据库连接有什么好处?我觉得使用单例而不是全局会使代码变得不必要地复杂化.

代码与全球

$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

单身代码

class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

如果有一种更好的方法来初始化除全局或单例之外的数据库连接,请提及它并描述它相对于全局或单例的优势.



1> 小智..:

我知道这已经过时了,但Dr8k的回答几乎就在那里.

当你考虑编写一段代码时,假设它会改变.这并不意味着你假设它将在未来的某个时刻提升它所带来的变化,而是要做出某种形式的改变.

让它成为一个目标,减轻未来改变的痛苦:全球化是危险的,因为它很难在一个地方进行管理.如果我希望将来能够识别数据库连接上下文怎么办?如果我希望它每隔5次关闭并重新打开它,该怎么办?如果我决定为了扩展我的应用程序而想要使用10个连接池,该怎么办?或者可配置数量的连接?

一个单身的工厂为您提供了灵活性.我设置它只需要很少的额外复杂性,并且获得的不仅仅是访问相同的连接; 我能够以一种简单的方式改变连接传递给我的方式.

请注意,我说单身工厂而不是简单的单身人士.单身人士与全球人士之间存在着微不足道的差异.正因为如此,没有理由建立一个单独的连接:为什么你可以花时间设置那个,而你可以创建一个常规的全局?

工厂得到的是为什么要获得连接,以及一个单独的位置来决定你将获得什么样的连接(或连接).

class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

然后,在6个月内,当你的应用程序超级出名并且得到dugg和slashdotted并且你决定需要多个连接时,你所要做的就是在getConnection()方法中实现一些池化.或者,如果您决定要使用实现SQL日志记录的包装器,则可以传递PDO子类.或者,如果您决定在每次调用时都需要新连接,则可以执行此操作.它很灵活,而不是僵化.

包括大括号在内的16行代码,可以节省数小时和数小时的重构次数.

请注意,我不认为这是"特征蠕变",因为我在第一轮中没有做任何功能实现.这是边界线"未来的蠕变",但在某些时候,"为今天的明天编码" 总是一件坏事的想法并不适合我.


不确定,但我认为你的意思是:public function getConnection(){if(!$ this-> db)$ this-> db = new PDO(...); return $ this-> db; }
我想在我正在做的项目中使用此代码.我可以引用此页面,如果是这样,该文本的许可证是什么?是CC-BY,BSD还是其他什么?我目前声称这是"未知 - 相信公共领域",但我想将其归结为正确的许可条件.
我认为我们应该在getConnection()方法中创建"$ db""$ this-> db",否则"private $ db"变量"未被使用",这在任何地方都没有正式引用.

2> Dr8k..:

我不确定我能回答你的具体问题,但是想建议全局/单一连接对象可能不是最好的想法,如果这是基于网络的系统.DBMS通常用于以有效的方式管理大量唯一连接.如果您正在使用全局连接对象,那么您正在做以下几件事:

    强制您的页面按顺序执行所有数据库连接并终止任何异步页面加载尝试.

    可能持有数据库元素上的打开锁定时间超过必要时间,从而降低整体数据库性能.

    最大化数据库可以支持的并发连接总数,并阻止新用户访问资源.

我相信还有其他潜在的后果.请记住,此方法将尝试为访问该站点的每个用户维持数据库连接.如果您只有一个或两个用户,则不是问题.如果这是一个公共网站并且您想要流量,那么可扩展性将成为一个问题.

[编辑]

在较大的缩放情况下,每次点击数据时创建新连接都可能很糟糕.但是,答案不是创建全局连接并将其重用于所有内容.答案是连接池.

通过连接池,可以维护许多不同的连接.当应用程序需要连接时,将检索池中的第一个可用连接,然后在其作业完成后将其返回到池中.如果请求连接且没有可用连接,则会发生以下两种情况之一:a)如果未达到允许的最大连接数,则打开新连接,或b)强制应用程序等待连接变为可用.

注意:在.Net语言中,默认情况下,连接池由ADO.Net对象处理(连接字符串设置所有必需的信息).

感谢Crad对此发表评论.


请注意,在PHP的情况下,"global"不会使PHP页面中的变量成为全局变量.它只是意味着可以从函数内访问它.

3> 小智..:

创建单例方法是为了确保只有一个类的实例.但是,因为人们将它用作快捷全球化的一种方式,所以它被称为懒惰和/或糟糕的编程.

因此,我会忽略全局和Singleton,因为两者都不是真正的OOP.

您正在寻找的是依赖注入.

您可以在http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection上查看与依赖注入相关的易于阅读的PHP信息(带示例)

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有