【问题标题】:Creating one PDO and accessing it from different scripts创建一个 PDO 并从不同的脚本访问它
【发布时间】:2013-12-10 17:42:01
【问题描述】:

我知道 PDO 不能序列化为会话,我可以使用单例,通过实例化访问 PDO,如本例 Use of PDO in classes。 我已经压缩了代码并删除了异常处理,例如为了 PDO 连接的所有必要细节。

class Database
{
public $db;
private static $instance;

private function __construct()
{
    $dsn = 'mysql:dbname=test;host=localhost;port=3306';
    $this->db = new PDO($dsn, 'user', 'password');
    echo 'You will see this when PDO is created or instantiated';
}

public static function getInstance()
{
    if (!isset(self::$instance))
    {
        $object = __CLASS__;
        self::$instance = new $object;
    }
    return self::$instance;
}
}

然后每个页面或脚本通过使用例如调用静态实例:

$database = Database::getInstance();
$stmt = $database->db->prepare('SELECT * FROM table');
$stmt->execute();

现在这一切都很好,但我的理解是每次调用实例时都会创建一个新的 PDO。有没有办法,不使用框架,例如Zend Registry,从一个页面到另一个页面传递 PDO,而不是每次都创建一个新的 PDO?我似乎找不到这个问题的答案。尽管它是单个实例,但在每个页面上重新连接到数据库似乎仍然是相当多余的。谢谢。

已解决

我认为最终这是PHP的限制,我所要求的实际上无法完成。感谢大家的帮助,不胜感激。

【问题讨论】:

  • 在您的情况下,一个新的 PDO 实例每个会话获取一次,而不是每次调用 Database::getInstance()
  • 为什么要返回自己的课程而不是 PDO?
  • @YourCommonSense 吧?如果他显然有一个包装器,他为什么要直接返回一个 PDO 实例?
  • Rain,我没有调用 session_start() 时怎么会这样?
  • @YourCommonSense 他在他的类的构造函数中创建了一个 PDO 实例,这是一个数据库抽象层。因此,也许他不想返回 PDO 的裸实例,而是返回他的类的实例,而后者又通过属性持有 PDO 的实例? (请注意,他表示为简洁起见删除了很多代码)

标签: php mysql pdo singleton


【解决方案1】:

PHP 资源的范围仅限于请求。也就是说,当您结束请求时,PHP 会清理资源。例如,关闭文件或数据库连接。您不可避免地需要为每个请求创建一个新的 PDO 实例。

但是您可以稍微降低创建该 PDO 实例的成本。我假设您希望在请求之间携带 PDO 对象,以避免打开新连接的开销。

MySQL 连接通常非常快,尤其是当您在 localhost 上进行连接时。所以可能没有必要进一步优化。

但是创建连接的开销仍然大于零,所以如果你想再减少一点开销,你可以使用持久连接:

$this->db = new PDO($dsn, 'user', 'password', array(PDO::ATTR_PERSISTENT => true));

这将在多大程度上提高您的表现?它根据您的流量水平和每个请求所做的工作量而有所不同。在您的情况下,净收益可能微不足道。

这是一个博客,作者在其中描述了一个基准测试并得出结论,他在 PHP 中的内存使用量减少了,每秒请求数增加了几倍。 http://blog.shay.co/pdo-persistent-connection-analysis/

但是从那篇博客中获取基准测试结果还是有一点保留的,因为所使用的测试脚本除了连接之外什么都不做任何事情。也就是说,他们不做任何查询,他们只是连接。持久连接对其他工作没有影响,只会影响连接速度。在真正的应用程序中,相对于在 PHP 中运行查询和操作结果,连接时间已经占了很小的比例。因此,减少已经占用的部分代码的开销,例如,2% 的时间只会产生很小的影响。


来自@AnthonyJrXu 的回复

老实说,我很少看到有人使用 PDO 的持久连接。性能差异通常很小。例外情况当然存在,因此值得您花时间测试并看看您在应用程序中获得了多少好处。

但通常最好花时间分析查询以获得最佳索引,或者将一些数据库查询卸载为 memcached 查询。

【讨论】:

  • 但是 OP 要求的不能完成(至少在 PHP 中不能),因此这个答案显示了为数不多的可行解决方案之一。
  • 感谢比尔,现在阅读博客。但根据您的经验,您以前从未见过这样做过吗?
  • 请参阅上面的编辑答案,该答案应阐明它与 OP 问题的关系。但我不指望@YourCommonSense 会扭转他毫无根据的反对票。
【解决方案2】:

我认为您想要的是应用程序中的依赖注入。您想要创建一个 PDO 实例并将该实例传递到您需要数据库连接的整个应用程序中。如果您将它用作前端控制器,这可以在您的 index.php 脚本中。

【讨论】:

  • Martin,一个前端控制器将用户路由到他想要的任何视图。一个更简单的例子是我没有控制器,但我只是重新加载 index.php,即使它是同一个页面,仍然会调用一个新实例来重新连接到数据库。我这样说对吗?非常感谢。
  • @Your Common Sense 如果您觉得这含糊不清,我很抱歉,我认为我的解释和示例很清楚,但感谢您的帮助。
  • @AnthonyJrXu 是的,每个页面请求都会创建一个新的 PDO 实例,但是一旦页面完成渲染,该实例也会被销毁。我认为您需要进一步研究 HTTP 和 PHP 请求生命周期。
  • @AnthonyJrXu 我不“觉得”它模棱两可,但确实如此。你没有清楚的地方。尤其是在谈到调用实例和提及框架时(因为它们显然也无济于事)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
  • 2013-03-25
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多