动态创建的数据源未传递给CakePHP中的关联模型

时间:2015-01-06 00:33:26

标签: php cakephp cakephp-2.0

我有一个模型 - 汽车 - 汽车有几个相关的模型,让我们考虑其中一个与hasMany关系链接的轮子 - 轮

在我的CarsController中,我使用以下代码动态生成数据源 -

$schemaName = $this->Session->read('User.schema'); 
$config = ConnectionManager::getDataSource('default')->config;
$config['database'] = $schemaName;
ConnectionManager::create($schemaName, $config);

然后我使用以下代码行在我的汽车模型中设置此数据源

$this->Car->setDataSource($schemaName);

在此之后我能够查询并操作Car,但是,如果我尝试使用以下语句对Wheel进行操作 - 我收到错误

$this->Car->Wheel->create();
$this->Car->Wheel->save($wheelData);

我得到的错误是 - 错误:[MissingTableException]在数据源默认值中找不到模型Wheel的表轮。

由于某种原因,数据源未从父模型传递到关联的子模型。如果我使用以下行在Wheel中显式设置数据源,那么一切正常。

$this->Car->Wheel->setDataSource($schemaName);

任何人都可以帮助阐明这种行为以及如何解决这个问题?我发现这个不方便的原因是我的父模型有几个相关的模型(还有相关的模型),并且在每个模型上单独设置数据源听起来不对。

附带问题 - 有没有办法在尝试动态创建数据源之前检查数据源是否已存在?我有一个包含整个代码的for循环,每次循环迭代最终都会创建一个新的数据源

我正在使用CakePHP 2.5.4

1 个答案:

答案 0 :(得分:4)

以下是一些将setDatasource()调用传递给关联模型的代码,如果您只希望Car模型通过其数据源将此代码放入Car模型中,如果您希望所有模型都通过,请将其放入在AppModel.php

public function setDatasource($datasource = null) {
    foreach (array_keys($this->getAssociated()) as $modelName) {
        $this->{$modelName}->setDatasource($datasource);
    }
    parent::setDatasource($datasource);
}

要回答您的评论,我会在public $dynamicDb = false中添加AppModel.php,这意味着false将是此变量的默认值,然后在您的模型中通过添加public $dynamicDb = true覆盖它,然后更改以上功能:

public function setDatasource($datasource = null) {
    foreach (array_keys($this->getAssociated()) as $modelName) {
        if ($this->{$modelName}->dynamicDb === true) {
            $this->{$modelName}->setDatasource($datasource);
        }
    }
    parent::setDatasource($datasource);
}

(我还没有测试过这个修正过的功能,因为我现在不在我的开发电脑上,但这是一个相当简单的改变而且它应该有效)

要在创建数据源之前检查数据源是否已存在,我可以看到两种可能的方法,一种是通过调用ConnectionManager::getDatasource($schemaName)并在数据源不存在时捕获异常,或者调用ConnectionManager::sourceList()和检查您的$schemaName是否在返回的数组中,这是第一个选项的实现:

$schemaName = $this->Session->read('User.schema'); 
try {
    ConnectionManager::getDatasource($schemaName)
} catch (MissingDatasourceException $e) {
    $config = ConnectionManager::getDataSource('default')->config;
    $config['database'] = $schemaName;
    ConnectionManager::create($schemaName, $config);
}

和第二个选项:

$datasources = ConnectionManager::sourceList();
$schemaName = $this->Session->read('User.schema'); 
if (!in_array($schemaName, $datasources)) {
    $config = ConnectionManager::getDataSource('default')->config;
    $config['database'] = $schemaName;
    ConnectionManager::create($schemaName, $config);
}

希望这有帮助