我和一个队友一起思考了一些 DAO 设计的东西,遇到了一个有趣的问题,我还没有找到任何最佳实践指南。
创建DAO对象时,DB连接应该在什么时候发生?我们已经讨论过实例化一个在构造函数中创建数据库连接的对象(然后在后续方法中使用它),并创建一个静态类来建立连接并在每次方法调用后将其拆除。
两者都基于环境具有明显的性能影响 - 静态对象对于一些间歇性调用很有用,而实例化一个保持连接的对象对于少数用户在短时间内的大量调用来说非常有用。
还有另一种方法可以做到这一点吗?也许在大多数情况下对性能会更好?
我和一个队友一起思考了一些 DAO 设计的东西,遇到了一个有趣的问题,我还没有找到任何最佳实践指南。
创建DAO对象时,DB连接应该在什么时候发生?我们已经讨论过实例化一个在构造函数中创建数据库连接的对象(然后在后续方法中使用它),并创建一个静态类来建立连接并在每次方法调用后将其拆除。
两者都基于环境具有明显的性能影响 - 静态对象对于一些间歇性调用很有用,而实例化一个保持连接的对象对于少数用户在短时间内的大量调用来说非常有用。
还有另一种方法可以做到这一点吗?也许在大多数情况下对性能会更好?
由于您已将其标记为mvc,我将假设您的 DAO 已经存在于模型层中。据我了解。DAO 负责与Data Mappers相同的任务,并将来自存储(可能是也可能不是 SQL 数据库)的信息提供给模型层中的域对象。
处理此问题的最佳方法是使用工厂,它在模型层中创建数据访问对象。这将有几个优点:
这就是我将如何实现类似的东西:
class DaoFactory
{
protected $connection = null;
protected $provider = null;
public function __construct( $provider )
{
$this->provider = $provider;
}
public function create( $name )
{
if ( $connection === null )
{
$connection = call_user_func( $this->provider );
}
$instance = new $name;
$instance->setConnection( $connection );
return $instance
}
}
用法看起来像这样:
$connectionProvider = function()
{
$instance = new \PDO('mysql:host=localhost;dbname=testdb;charset=utf8',
'username', 'password');
$instance->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$instance->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
return $instance;
};
$daoFactory = new DaoFactory( $connectionProvider );
然后将$daoFactory变量传递给创建 DAO 所需的任何对象。这样,如果需要,您可以轻松地用完全不同的东西替换工厂(只要它实现相同的create()方法足迹)。您的领域业务逻辑绝不会受到这种变化的影响。
使用这个工厂的对象完全不知道甚至存在数据库连接,DAO 需要它来运行。当您甚至不需要建立与数据库的连接时,您甚至可能会遇到一些情况。
Rant
由于您的代码库中有数据访问对象,这表明您正在尝试使用 OOP。或者至少是类似的东西。但是静态类/函数/变量不是 OOP 范式的一部分。如果你有一个只包含静态方法和少量静态变量的类,那么你实际上所做的只是带有全局变量的简单 php 函数,包装在一个命名空间中,它恰好看起来像类。PHP 社区倾向于将此 COP(面向类的编程)称为笑话,但本质上它是过程代码。