用于数据库连接的全局或单例?

2021-12-22 00:00:00 design-patterns singleton php

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

What is the benefit of using singleton instead of global for database connections in PHP? I feel using singleton instead of global makes the code unnecessarily complex.

$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();
    .
    .
    .
}

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

If there's a better way of initializing database connection other than global or singleton, please mention it and describe the advantages it have over global or singleton.

推荐答案

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

I know this is old, but Dr8k's answer was almost there.

当您考虑编写一段代码时,假设它会发生变化.这并不意味着您假设它会在未来的某个时间点对它进行各种更改,而是会进行某种形式的更改.

When you are considering writing a piece of code, assume it's going to change. That doesn't mean that you're assuming the kinds of changes it will have hoisted upon it at some point in the future, but rather that some form of change will be made.

将其作为目标可以减轻未来进行更改的痛苦:全局是危险的,因为很难在一个地方进行管理.如果我希望将来知道该数据库连接上下文怎么办?如果我希望它每使用 5 次就关闭并重新打开,该怎么办?如果我决定为了扩展我的应用程序我想使用 10 个连接池怎么办?还是可配置的连接数?

Make it a goal mitigate the pain of making changes in the future: a global is dangerous because it's hard to manage in a single spot. What if I want to make that database connection context aware in the future? What if I want it to close and reopen itself every 5th time it was used. What if I decide that in the interest of scaling my app I want to use a pool of 10 connections? Or a configurable number of connections?

单例工厂为您提供了这种灵活性.我用很少的额外复杂性来设置它,并且获得的不仅仅是访问相同的连接;我获得了稍后以简单方式更改该连接传递给我的方式的能力.

A singleton factory gives you that flexibility. I set it up with very little extra complexity and gain more than just access to the same connection; I gain the ability to change how that connection is passed to me later on in a simple manner.

请注意,我说的是 singleton factory 而不是简单的 singleton.单身人士和全球人士之间几乎没有什么区别,真的.正因为如此,没有理由使用单例连接:当您可以创建一个常规的全局连接时,为什么还要花时间设置它?

Note that I say singleton factory as opposed to simply singleton. There's precious little difference between a singleton and a global, true. And because of that, there's no reason to have a singleton connection: why would you spend the time setting that up when you could create a regular global instead?

工厂给你的是为什么要获得联系,以及一个单独的地点来决定你将获得什么联系(或联系).

What a factory gets you is a why to get connections, and a separate spot to decide what connections (or connection) you're going to get.

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 个月内,当您的应用程序非常出名并被挖出和斜线标记并且您决定需要多个连接时,您所要做的就是在 getConnection() 方法中实现一些池化.或者,如果您决定需要一个实现 SQL 日志记录的包装器,您可以传递一个 PDO 子类.或者,如果您决定在每次调用时都需要一个新连接,则可以这样做.它是灵活的,而不是僵硬的.

Then, in 6 months when your app is super famous and getting dugg and slashdotted and you decide you need more than a single connection, all you have to do is implement some pooling in the getConnection() method. Or if you decide that you want a wrapper that implements SQL logging, you can pass a PDO subclass. Or if you decide you want a new connection on every invocation, you can do do that. It's flexible, instead of rigid.

16 行代码,包括大括号,这将为您节省数小时、数小时和数小时的重构时间,以实现极其相似的内容.

16 lines of code, including braces, which will save you hours and hours and hours of refactoring to something eerily similar down the line.

请注意,我不考虑这种功能蠕变",因为我在第一轮中没有进行任何功能实现.它是Future Creep"的边界线,但在某些时候,今天为明天编码"的想法总是对我来说是件坏事.

Note that I don't consider this "Feature Creep" because I'm not doing any feature implementation in the first go round. It's border line "Future Creep", but at some point, the idea that "coding for tomorrow today" is always a bad thing doesn't jive for me.

相关文章