问题描述
我正在研究一些需要连接到两个单独的数据库的API,这些数据库包含相似的表但数据不同。
我已经在app.PHP
和app_local.PHP
中配置了两个数据源,并且两个数据源都是可以访问的。
通过一些研究,我发现ConnectionManager::alias
应该是我所需要的,因此我想到了:
// Fetching `energy` DB data
ConnectionManager::alias('energy','default');
$energy = $this->Users->find()->first();
debug($energy);
ConnectionManager::dropAlias('default');
// Fetching `default` (gas) DB data
$gas = $this->Users->find()->first();
debug($gas);
问题是,如果我像这样运行那些查询,则调试将提供相同的数据,这意味着energy
数据库中的数据将被打印两次。
但是:
看起来只有第一个数据源实际上在使用。
我做错了什么?
解决方法
实例化表类后,它将保存实例化时分配给它的连接实例(connection
的{{1}}选项)和表实例时创建的实例。首先尝试获取连接(\Cake\ORM\Table::__construct()
)。
因此,仅删除别名是不会做任何事情的,表上的下一次调用将使用表已保存的连接实例,而不会尝试再次自行获得连接。
由于您希望更改连接影响所有内容,因此必须在删除连接别名后清除表注册表,然后再次加载表,以便使用实际的\Cake\ORM\Table::getConnection()
连接再次创建表(如果您只想影响特定的实例,则可以通过default
分配一个新的连接实例)。为了避免在创建别名时遇到与已经创建的表实例相同的问题,您很可能还应该在那个之后清除注册表。
基本示例:
setConnection()
如您所见,这不仅需要再次加载模型/表,而且还需要在属性上取消设置实例,否则ConnectionManager::alias('energy','default');
$this->getTableLocator()->clear();
// table instances created after this point will respect the alias
$this->Users = null;
$this->loadModel('Users');
$energy = $this->Users->find()->first();
ConnectionManager::dropAlias('default');
$this->getTableLocator()->clear();
// table instances created after this point will use the non-aliased connection
$this->Users = null;
$this->loadModel('Users');
$gas = $this->Users->find()->first();
不会实际加载表,而是返回该实例。已在loadModel()
属性上设置。
我建议您切换到通过表定位器(甚至在控制器中)来获取模型,那样您就可以跳过这些笨拙的未设置内容,并降低了意外访问存储在{{1 }}:
$this->Users
您可能还应该考虑在服务的某个位置集中此连接交换。