cakephp - 对同一模型使用多个数据库
问题描述
我正在研究一些需要连接到两个独立数据库的 API,其中包含相似的表但不同的数据。
我已经在我的app.php
and中配置了两个数据源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
数据库的数据会被打印两次。
但:
- 如果我只运行
energy
find 它会给我能源数据库的正确结果。 - 如果我只运行
gas
find 它会给我来自气体数据库的正确结果。
看起来实际上只使用了第一个数据源。
我做错了什么?
解决方案
一旦一个表类被实例化,它将保存在实例化时分配给它的连接实例(connection
选项\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()
实际上不会再次加载表,而是返回已在$this->Users
属性上设置的实例。
我建议您切换到通过表定位器获取模型,即使在您的控制器中,这样您就可以跳过这个尴尬的未设置内容,并且您可以降低意外访问存储在属性上的旧实例的风险,例如$this->Users
:
ConnectionManager::alias('energy', 'default');
$this->getTableLocator()->clear();
$energy = $this->getTableLocator()-get('Users')->find()->first();
ConnectionManager::dropAlias('default');
$this->getTableLocator()->clear();
$gas = $this->getTableLocator()-get('Users')->find()->first();
您可能还应该考虑将此连接切换集中在服务中的某个位置。
推荐阅读
- java - java初学者石头剪刀布游戏
- angular - Angular 9.x 应用程序无法在 IE11 中加载
- javascript - Empty 不能在 rxjs 中完成 observable
- c++ - 如何比较数组并检查其顺序是否正确
- r - 较长的对象长度不是使用 MAP2 函数的较短对象长度的倍数
- java - 如何处理 OAuth 网络客户端异常
- css - CSS 不适用于 Shadow DOM 中的 Angular 元素(Web 组件)
- c# - c# Xamarin UWP/Android 服务器 - 客户端套接字 tcp 无法正确连接
- forms - (关于 POST 请求的问题)有没有办法发送 POST 请求,然后在外部出现 302 的情况下取回检索到的资源?
- django - Django-templated-email 不发送电子邮件