【问题标题】:Is this how lazy connecting of a database connection is supposed to be?数据库连接的延迟连接应该是这样吗?
【发布时间】:2014-05-11 17:18:01
【问题描述】:

所以我对在 OOP 中连接到数据库的好方法做了一些研究。如果您在我的数据库模型中查看我的 connect() 方法,我只会在我即将查询 时才连接,如果还没有连接。我认为它被称为 惰性连接,我在 SO answer 上偶然发现了它。

不是说为整个应用只建立1个数据库连接吗?

如果我在文件 A 中执行 new Database() 并在文件 B 中执行 new Database(),仍然会有两个连接。

如果有帮助的话,我正在使用微型 MVC 框架。

class Database
{
    private $pdo;
    private $host;
    private $databse;
    private $username;
    private $password;

    public function __construct()
    {
        $this->host     = Config::get('mysql/host');
        $this->database = Config::get('mysql/database');
        $this->username = Config::get('mysql/username');
        $this->password = Config::get('mysql/password');
    }

    public function query($sql, $params)
    {
        $this->connect();

        $sth    = $this->pdo->prepare($sql);
        $params = is_array($params) ? $params : [$params];

        if ($sth->execute($params)) {
            return $sth->fetch(PDO::FETCH_OBJ);
        }
    }

    private function connect()
    {
        if (!$this->pdo) {
            try {
                $this->pdo = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database . ';charset=utf8', $this->username, $this->password);
            } catch (Exception $e) {
                die($e->getMessage());
            }
        }
    }
}

【问题讨论】:

标签: php pdo lazy-loading


【解决方案1】:

我很想对上述答案发表评论,但声誉使我无法这样做。但是,我必须确保人们不会阅读这些内容并相信这是真实的或良好的做法。

主题: 单个数据库连接的想法是好的,除非它不是。您可能必须连接到第二个,然后一个单身人士会阻碍您这样做。 配置也要用实参:

  1. 您希望能够建立多个连接并且不能,因为 Config 类不允许这样做。
  2. 该类与Config 类硬耦合
  3. 'mysql/host' 这样在代码中浮动的魔术字符串也不是一个好主意。有人可能会出现并喜欢在配置中以不同的方式称呼它。如果你只使用参数来配置这个问题就消失了。
  4. 您希望能够清楚地看到一个类的依赖关系。隐藏它需要 Config 和 4 个参数的事实只会迫使您在每次想要使用它时查看实现。

关于在Session中存储连接:

  1. 有什么意义?您无法为其他 PHP 运行保护它。
  2. 序列化是不可能的,因为它是一种资源。
  3. 如上所述:如果您将对象存储在 Session 中以全局使用它们,则可能会隐藏依赖关系。

http://php.net/manual/en/intro.session.php

【讨论】:

  • 回复您的答案(并投反对票)。 **单个数据库连接非常有用。当需要第二个连接时,OP 自然会发现通过Config 类传递数据库连接信息需要调整。在我看来,这不是问题的主要焦点。 **为什么将连接存储在 Session var 中?同意需要在每次页面加载时重新建立连接,并且将提供一个全局变量。对我来说,使用$_SESSION['db'] 之类的东西是为了方便存储全局变量并且更易于维护。
  • 我不同意,因为大量可维护性来自于资源和对象在代码中具有清晰路径这一事实。使用像 $_SESSION 这样的变量意味着您的代码中有一个不明显的要求。由于对 $_SESSION 的依赖,代码不可重用。如果您想在没有上下文的上下文中运行代码怎么办?我确实明白这一点:“当你到达它时过桥”。但是,您甚至不需要再构建它,因为那里有很好的框架可以使这变得更容易,您可以专注于重要的业务代码。
  • 很公平。我删除了对 $_SESSION 的引用作为全局变量的示例。除此之外,并不是每个人都选择解决方案框架。对于大部分应用程序,我支持在一个简单的全局变量中重用连接的有用性。感谢您对编码方法的反馈。
【解决方案2】:

希望对此事有所了解还为时不晚。您混合了两个概念 - 1. 延迟加载(在本例中为延迟连接),以及 2. 持久连接。

仅当进行查询时,发布的代码才能正确建立实际的数据库连接。代码的正确性取决于代码的使用方式。考虑以下伪调用:

  1. 实例化调用构造函数的数据库类
  2. 显式调用连接函数
  3. 进行查询

上述顺序抵消了惰性连接的好处,因为无论如何都会建立连接。但是,如果删除第 2 步,查询函数将调用 connect,然后它将创建到数据库的真实连接。

为什么这很有用?在复杂的项目中,连接处理程序通常包含在某些头文件中。数据库查询是在各种组件中进行的。在进行查询时,数据库连接必须准备好。因此,即使在不从数据库加载任何内容的页面上也会创建连接。请记住,TCP 连接是宝贵的服务器资源。建立太多未使用的连接只是浪费。一种惰性连接方法正好解决了这个问题。

持久连接是一个不同的概念。这意味着在页面会话结束时,连接没有关闭。当需要一个新的连接时,PHP 会寻找一个“相同的”连接来重用。

为了完整起见,我想指出,长连接也不等同于连接池,虽然长连接可以看成是1的连接池。

【讨论】:

    【解决方案3】:

    有选项https://www.php.net/manual/en/pdo.connections.php PDO::ATTR_PERSISTENT。

    如果你使用这个选项,那么 php 不会关闭连接,只需重置一个连接并重用它。(如连接池)

    如果你真的想使用惰性数据库连接,(只有在需要做某事时通信数据库服务器)那么你只能让你的代码像https://github.com/thumbtack/querycache

    【讨论】:

      【解决方案4】:

      只有一个类的实例,你需要单例模式

      Creating the Singleton design pattern in PHP5

      不过,您可以轻松地将其添加到现有课程中。

      【讨论】:

      【解决方案5】:

      如果您将 new Database() 的结果存储在全局变量中,那么您可以重复使用它并为整个应用程序建立一个连接。

      你是对的,如果你在文件 A 中执行 new Database() 并在文件 B 中执行 new Database(),将会有两个连接。

      您的代码的整体概念与我使用的类似,并且运行良好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多