【问题标题】:Cakephp 2 multiple DBsCakephp 2 多个数据库
【发布时间】:2012-08-13 20:57:09
【问题描述】:

我想根据域切换数据库,从另一个数据库中选择凭据,但我无法切换..

AppController.php

// Select username, password and database based on domain
$this->Company->find('first', [...]);

if ($company) {
    // Connect to second database, droping connection from first.
    $dataSource = ConnectionManager::getDataSource('default');
    $dataSource->config['login'] = $company['Company']['dbuser'];
    $dataSource->config['password'] = $company['Company']['dbpass'];
    $dataSource->config['database'] = $company['Company']['dbname'];

    /**
     * PROBLEM START HERE:
     * Here, need to use new database settings, and, this case
     * Company table does not exists, but I always get it, so,
     * I think I am connected with the first and not second connection.
     */
    print_r($this->Company->find('first'));
}

我该如何纠正这个问题?

编辑

我试过没有成功:

ConnectionManager::drop('default');
ConnectionManager::create('default', $settings);

一个print_r(ConnectionManager::create('default', $settings))返回:

[... lots of things ... ]
[config] => Array
    (
        [persistent] => 
        [host] => localhost
        [login] => login
        [password] => password
        [database] => database
        [port] => 3306
        [datasource] => Database/Mysql
        [prefix] => 
    )
[... more things ... ]

编辑 2

现在,我可以切换数据库,但是,公司模型总是获取旧的数据库设置。

FooController.php

<?php
App::uses('AppController', 'Controller');

class FooController extends AppController {
    var $uses = array('Foo', 'Company');

    public function index() {
        echo'<pre>';
        print_r($this->Company->find('first')); // Here I get from old settings
        print_r($this->Foo->find('first')); // Here I gete from new settings
        echo'</pre>';

        $this->layout = false;
        $this->render(false);
    }
}

AppController.php

public function beforeFilter() {
    $company = ClassRegistry::init('Company')->find('first');
    $settings = array(
        'datasource' => 'Database/Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'login' => $company['Company']['dbuser'],
        'password' => $company['Company']['dbpass'],
        'database' => $company['Company']['dbname'],
        'prefix' => ''
    );

    ConnectionManager::getDataSource('default')->disconnect();

    ConnectionManager::drop('default');
    ConnectionManager::create('default', $settings);

    ConnectionManager::getDataSource('default')->connect();
}

【问题讨论】:

  • 您可以查看$dataSource 的详细信息吗?它可能仍然有一些东西链接到旧连接。
  • @rlcabral 查看更新的问题

标签: php cakephp cakephp-2.1


【解决方案1】:

看起来您需要动态创建配置并即时更改配置。我不知道这是否可行,但它可能会引导您找到答案。

首先,我们需要为要使用的数据源创建一个配置。为此我们可以使用ConnectionManager::create

接下来,我们需要即时更改配置,为此我们可以使用Model::setDataSource

我没有尝试过,但它看起来应该这样做。如果有问题,请发表评论,以便我更新答案。

编辑:这可能不起作用,因为每个模型都需要更改为新的数据源。有一个 ConnectionManager::drop() 方法可以用来删除 default 配置,然后 ConnectionManager::create('default', array(...)); 可能会使用新的默认值。

【讨论】:

  • 我已经删除并创建了一个新的默认数据源,但是,我无法得到我想要的。
  • 之后尝试ConnectionManager::getDataSource()-&gt;reconnect();。或->断开连接();首先然后更改数据源设置然后 ->connect();
  • 现在,我可以连接第一个和第二个数据库了。如果我在两个数据库中都有company 表,我总是从错误的数据库中获取结果(数据源更改之前的默认连接)..
  • 目前不确定。在进行 find 调用时,模型使用 $this-&gt;getDataSource(); 返回 ConnectionManager::getDataSource($this-&gt;useDbConfig); $this-&gt;useDbConfig 应该使用我们已更改为的“默认”。
  • 是的,但是,我不知道为什么这不会发生。
【解决方案2】:

您可以在数据库配置文件中切换数据库。

如下配置你的 Config/database.php 文件:

<?php
class DATABASE_CONFIG {

    // config for e.g. localhost
    public $default = array(
        'datasource' => 'Database/Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'root',
        'password' => 'xxxxx',
        'database' => 'cake',
        'encoding' => 'utf8'
    );

    // DB config specifically for your domain
    public $domain_x = array(
        'datasource' => 'Database/Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'username_at_hosting_provider',
        'password' => '087bJ#ytvh&^YU#T',
        'database' => 'blabla_cake',
        'encoding' => 'utf8'
    );

    public function __construct(){
        // switch config depending on domain / env('HTTP_HOST')
        if(env('HTTP_HOST')=='domain_x.com'){
            $this->default = $this->domain_x;
        }
        // otherwise keep $this->default
    }
}

编辑:

回答您的问题似乎有点太快了:它并没有真正涵盖您的问题。对不起!

【讨论】:

    【解决方案3】:

    好的,所以我设法在 AppModel 中创建 __construct 函数来解决这个问题,并将所有代码删除默认数据源并使用新配置创建另一个。像这样的:

    AppModel.php

    public function __construct($id = false, $table = null, $ds = null)
    {
        App::uses('CakeSession', 'Model/Datasource');
    
        parent::__construct($id, $table, $ds);
    
        if ($this->useDbConfig == 'default') {
            // Change the datasource config
            $user = CakeSession::read('Auth.User');
            $this->changeDataSource($user);
        }
    }
    
    
    
    public function changeDataSource($config)
    { 
        ...
        ...
        ...
        $dados = array();
        $dados['database']   = $config['titulo_bd'];
        $dados['host']       = $config['host_bd'];
        $dados['login']      = $config['login_bd'];
        $dados['password']   = $config['senha_bd'];
        $dados['datasource'] = 'Database/Mysql';
        $dados['persistent'] = false;
        $dados['prefix']     = '';
        $dados['encoding']   = 'utf8';
    
    
        ConnectionManager::create('default', $dados);
        ConnectionManager::getDataSource('default')->connect();
    }
    

    【讨论】:

    • 嘿!为什么要将敏感数据存储到用户会话中?
    • 确实如此。我只是想解决这个烦人的问题而忘记这一点。你有什么建议?
    • 我使用存储数据库数据的表解决了这个问题(请参阅 Security::rijndael 以安全地存储密码)。
    • 感谢@GabrielSantos!
    【解决方案4】:

    我的情况非常相似。就我而言,我有两种类型的连接。一种是使用 Config/database.php 文件进行连接配置的默认核心连接。第二个是动态配置,它使用为登录用户保存的数据库详细信息。因此,对于一些特定操作,我必须在默认数据库连接和基于用户的数据库连接之间切换。它是这样出现的。

    从默认文件切换到基于用户的数据库连接

    try {
      ConnectionManager::getDataSource('default')->disconnect();
      ConnectionManager::drop('default');
      ConnectionManager::create('default', $this->config);
      ConnectionManager::getDataSource('default')->connect();
      $db = ConnectionManager::getDataSource('default');
    } catch (MissingDatabaseException $e) {
      $this->Session->setFlash($e->getMessage()); 
    }
    

    其中 $this->config 是基于用户的连接。

    要切换回基于默认文件的连接,我会这样做:

    try {
      ConnectionManager::getDataSource('default')->disconnect();
      ConnectionManager::drop('default');
      $dbconfig = new DATABASE_CONFIG();
      ConnectionManager::create('default', $dbconfig->default);
      ConnectionManager::getDataSource('default')->connect();
      $db = ConnectionManager::getDataSource('default');
    }
    

    其中 $dbconfig->default 即 $default 包含我在 Config/database.php 中的默认连接配置

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多