如何为PHP PDO创建“模式切换”?

5
我目前正在使用PHP PDO访问我的数据库,这一切都非常完美。但是,我将在服务器上添加读取副本,因此我希望相应地调整我的代码。
我的当前计划是存储一个包含数据库凭据详细信息的数组。一个是“读和写”用于主MySQL数据库,另外可以有多个“读副本”的凭据。
我想做的是向PDO类中添加一个名为“mode”的方法,通过传递一个模式,例如“读”或(默认)“写”。通过传递这个模式(例如 $dbh->mode("read"); ),它可以查找随机读取副本的详细信息(无论哪个都行),并使用这些详细信息进行连接。然后,一旦从我的副本中读取完成,再使用 $dbh->mode("default") 将其重新设置为写模式,以便可以使用INSERT、UPDATE等操作。
这是否可以在不仅仅是销毁PDO对象并创建一个新对象的情况下进行?连接详细信息是否可以在对象已经存在之后简单地更改?
到目前为止,我只有以下内容(几乎没有什么内容,但认为这是一个开始)。
Class SwitchablePDO extends PDO
{
    public function mode($mode = "default") 
    {
        // Use the credentials for my master read and write server by default

        if($mode == "read")
        {
            // Use one the credentials for my read replicas (randomly choose)
        }

    }
}

希望能得到关于此事的任何帮助!


这是必要的吗?我认为大多数人会使用几个数据库用户来完成这个任务(一个只能读取,一个具有完全访问权限),然后为每个用户使用单独的数据库连接。 - Ozzy
这样做并不能将负载分配到读副本上。每个读副本的连接细节都是不同的。如果我每次想要切换到读或写时都创建一个新的PDO对象,我仍然需要一种方法来实现这一点。这种方式(希望)将允许我一次只使用一个连接对象/类实例,而不必使用$dbh_write->query()和$dbh_read->query()。 - Schodemeiss
2个回答

2
我宁愿设置完全不同的数据库连接对象,也不想处理模式。使用模式,你不可避免地会遇到这样的情况:一段代码没有设置模式,依赖于前一段代码的模式,在不同的上下文中调用时会失败。这被称为顺序耦合
通过工厂方法或依赖注入容器提供多个对象,确保每段代码都指定所需的数据库连接,如主库或从库。
此外,避免使用主/从作为名称,而是使用与要执行的任务类型相关的名称,比如分析,这样可以在不查找所有相关代码的情况下更改将使用哪个服务器。

1
为读模式和写模式创建单独的类,然后将它们分配给 SwitchablePDO 类中的私有/受保护属性。调用 mode() 方法只需设置要使用的属性即可。以下是一些伪代码示例:
class WriteablePDO extends PDO
{
    // methods
}

class ReadablePDO extends PDO
{
    // methods
}

class SwitchablePDO
{
    protected $_mode = 'read'; // default
    protected $_read;
    protected $_write;

    public function __construct()
    {
        $this->_read = new ReadablePDO();
        $this->_write = new WriteablePDO();
    }

    public function mode($key)
    {
        if ($key === 'read')
        {
            $this->_mode = '_read';
        }
        elseif ($key === 'write')
        {
            $this->_mode = '_write';
        }
    }

    public function __call($method, $arguments)
    {
        return call_user_func_array(array($this->{$this->_mode}, $method), $arguments);
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接