16

好的,我的第一个问题被修改了很多次,所以我选择删除它并重新提出我的问题。我制作了一个具有不同型号名称的小型测试用例项目,以找到适合我的问题的解决方案。

警告:不要将数据库表混在一起

动机:出于法律和性能问题,我将用户数据分离到多个数据库中。

目前,我正在开发一个CakePHP项目,该项目有多个User's 并且每个User都有自己的数据库和多个cars之一)。现在,我需要先解释一下:

每个User人都有自己的数据库(不是表,是数据库),所以数据库名称如下。

  • [DATABASE] app(这是应用程序的主数据库)
    • [桌子]users
    • [TABLE] permissions与此问题无关
  • [DATABASE] app_user1User.id1 拥有整个数据库
    • [TABLE] cars(完全由1拥有的表)User.id
  • [DATABASE] app_user2User.id2 拥有整个数据库
    • [TABLE] cars(完全由2拥有的表)User.id
  • ETC...

我画了一张小图,可以阐明数据库/定义及其与模型的关系:

如何在 CakePHP 中为一个模型动态使用多个数据库

问题!!!

我不知道要连接到哪个数据库User,直到登录。User和他们的数据库是动态创建的,所以我不能使用app/Config/database.php.

所以我目前正在编写ModelConnectionManager类的扩展来绕过 CakePHP 的基本数据库行为。所以Car模型知道要使用哪个数据库。但我只是觉得这可以更容易地完成!

所以我想这一切都归结为一个问题:

有没有更简单的方法来做到这一点?!

感谢任何愿意花时间和精力阅读和理解我的问题的人!

4

5 回答 5

38

这位先生奥利维尔)也有同样的问题!(一年前)Controller为s!写了一个小改编!它非常小,事实证明,它适用于1.32.x

无论如何,这是我的最终解决方案,我将其放入app/Model/AppModel.php

class AppModel extends Model
{
  /**
   * Connects to specified database
   *
   * @param String name of different database to connect with.
   * @param String name of existing datasource
   * @return boolean true on success, false on failure
   * @access public
   */
    public function setDatabase($database, $datasource = 'default')
    {
      $nds = $datasource . '_' . $database;      
      $db  = &ConnectionManager::getDataSource($datasource);

      $db->setConfig(array(
        'name'       => $nds,
        'database'   => $database,
        'persistent' => false
      ));

      if ( $ds = ConnectionManager::create($nds, $db->config) ) {
        $this->useDbConfig  = $nds;
        $this->cacheQueries = false;
        return true;
      }

      return false;
    }
}

这是我在我的app/Controller/CarsController.php

class CarsController extends AppController
{
  public function index()
  {
    $this->Car->setDatabase('cake_sandbox_client3');

    $cars = $this->Car->find('all');

    $this->set('cars', $cars);
  }

}

我敢打赌,我不是第一个或最后一个遇到这个问题的人。所以我真的希望这些信息能找到人们和 CakePHP 社区。

于 2012-11-05T00:45:44.003 回答
9

我不喜欢在代码中写下数据库的实际名称的想法。对于多个数据库,您有 database.php 文件,您可以在其中设置任意数量的数据库。

如果您想动态“切换”特定模型的数据库,请使用setDataSource方法。(见这里

例如,如果您有两个数据库,您可以在 database.php 文件中将它们定义为“默认”和“沙盒”,例如。

然后,在您的代码中:

$this->Car->setDataSource('sandbox');

沙盒是配置的名称,数据库的实际名称只在database.php文件中写入一次。

于 2013-01-31T09:47:47.983 回答
1

您始终可以在 mysql 中使用完整符号查询任何数据库。例如:

SELECT * FROM my_schema_name.table_name;

蛋糕方式:

$db = $this->getDataSource();
$query = array(
    'fields' => array('*'),
    'table' => 'my_schema_name.table_name'
);
$stmt = $db->buildStatement($query, $this);
$result = $db->execute($stmt);
于 2014-05-02T21:35:29.363 回答
1

在你的 database.php

public $mongo = array(
    'datasource' => 'Mongodb.MongodbSource',
    'database' => 'database_name_mongo',
    'host' => 'localhost',
    'port' => 27017,
);

在您的控制器中,您可以使用

$this->Organisation->setDataSource('mongo');

然后应用查询

this->Organisation->find('all');
于 2017-01-23T05:56:08.527 回答
1

这是公认的答案。如果新数据源已经存在,这将防止错误:

public function setDatabase($database, $datasource = 'default')
{
    $newDatasource = $datasource . '_' . $database;
    try {
        // return the new datasource if it's already existed
        $db = ConnectionManager::getDataSource($newDatasource);
        $this->useDbConfig  = $newDatasource;
        $this->cacheQueries = false;
        return true;
    } catch (Exception $e) {
        // debug($e->getMessage());
    }

    $db  = ConnectionManager::getDataSource($datasource);
    $db->setConfig(array(
        'name'       => $newDatasource,
        'database'   => $database,
        'persistent' => false
    ));

    if ( $ds = ConnectionManager::create($newDatasource, $db->config) ) {
        $this->useDbConfig  = $newDatasource;
        $this->cacheQueries = false;
        return true;
    }

    return false;
}
于 2018-02-27T10:30:51.800 回答