Under PHP 7.0.22, CakePHP 2.10.3, error: the datasource configuration tmp was not found in Solution of database.php. (dynamically set data source object)
1. Under PHP 7.0.22 and CakePHP 2.10.3, error: the datasource configuration tmp was not found in database.php., as shown in Figure 1
2. Print $this->UsedbConfig, its value is TMP, as shown in Figure 2
3. Make sure that $tmp does not exist in database.php, as shown in Figure 3
4. However, it was normal to confirm in CakePHP 2.6.4 before, and I decided to compare the difference and find the difference (Note: After the core library was modified, after the upgrade, the _init() of the core library is restored), as shown in Figure 4
\lib\cake\model\connectionmanager.php
Note: After the core library is modified, after the upgrade, the _init() of the core library is restored
5. Print static::$config in the getDataSource method of \lib\cake\model\ConnectionManager.php, as shown in Figure 5
6, print the result, make sure that there is no $tmp, as shown in Figure 6
7. The current requirement should be, without modifying the core library, ensure that $tmp exists in static::$config, and view the previous implementation, as shown in Figure 7
\app\model\appmodel.php
getTenantEnv($tenantid);
$this->log($conn);
Cache::write($tenantid,$conn,'_cake_config_');
}
return $conn;
}
public function setDataSource($dataSource = null) {
if($_GET['tenantid']){
$tenantid = [addslashes($_GET['tenantid'])];
}else{
preg_match('@^(?:http://)?([^/]+)@i', FULL_BASE_URL, $matches);
$tenantid = explode('.', $matches[1]);
}
$conn = $this->getDbConfig($tenantid[0]);
if(!$conn) die('系统错误506,无法链接数据库');
$this->useDbConfig = $dataSource = 'tmp';
$oldConfig = $this->useDbConfig;
if ($dataSource) {
$this->useDbConfig = $dataSource;
}
$config = new stdClass();
$config->tmp = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' =>$conn['db_info']['host'],
'login' => $conn['db_info']['login'],
'password' => $conn['db_info']['password'],
'database' => $conn['db_info']['database'],
'port' => 3306,
'prefix' => 'operation_',
'encoding' => 'utf8'
);
// if(!$conn){
// pr($config->tmp);
// $config->tmp = array(
// 'datasource' => 'Database/Mysql',
// 'persistent' => false,
// 'host' => '127.0.0.1',
// 'login' =>'root',
// 'password' =>'root',
// 'database' =>"jifen",
// 'port' => 3306,
// 'prefix' => 'operation_',
// 'encoding' => 'utf8'
// );
// }
// $this->log($config->tmp);
ConnectionManager::$config = $config;
$db = ConnectionManager::getDataSource($this->useDbConfig);
if (!empty($oldConfig) && isset($db->config['prefix'])) {
$oldDb = ConnectionManager::getDataSource($oldConfig);
if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix === $oldDb->config['prefix'])) {
$this->tablePrefix = $db->config['prefix'];
}
} elseif (isset($db->config['prefix'])) {
$this->tablePrefix = $db->config['prefix'];
}
$schema = $db->getSchemaName();
$defaultProperties = get_class_vars(get_class($this));
if (isset($defaultProperties['schemaName'])) {
$schema = $defaultProperties['schemaName'];
}
$this->schemaName = $schema;
//pr($config->tmp);
}
?>
8. Dynamically create a DataSource object with the given name and settings at runtime, so there is no need to modify the core library, as shown in Figure 8
\app\model\appmodel.php
getTenantEnv($tenantid);
$this->log($conn);
Cache::write($tenantid,$conn,'_cake_config_');
}
return $conn;
}
public function setDataSource($dataSource = null) {
if($_GET['tenantid']){
$tenantid = [addslashes($_GET['tenantid'])];
}else{
preg_match('@^(?:http://)?([^/]+)@i', FULL_BASE_URL, $matches);
$tenantid = explode('.', $matches[1]);
}
$conn = $this->getDbConfig($tenantid[0]);
if(!$conn) die('系统错误506,无法链接数据库');
$dataSource = 'tmp';
$config = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' =>$conn['db_info']['host'],
'login' => $conn['db_info']['login'],
'password' => $conn['db_info']['password'],
'database' => $conn['db_info']['database'],
'port' => 3306,
'prefix' => 'operation_',
'encoding' => 'utf8'
);
ConnectionManager::create($dataSource, $config);
$this->useDbConfig = $dataSource;
$oldConfig = $this->useDbConfig;
if ($dataSource) {
$this->useDbConfig = $dataSource;
}
$db = ConnectionManager::getDataSource($this->useDbConfig);
if (!empty($oldConfig) && isset($db->config['prefix'])) {
$oldDb = ConnectionManager::getDataSource($oldConfig);
if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix === $oldDb->config['prefix'])) {
$this->tablePrefix = $db->config['prefix'];
}
} elseif (isset($db->config['prefix'])) {
$this->tablePrefix = $db->config['prefix'];
}
$schema = $db->getSchemaName();
$defaultProperties = get_class_vars(get_class($this));
if (isset($defaultProperties['schemaName'])) {
$schema = $defaultProperties['schemaName'];
}
$this->schemaName = $schema;
}
?>
9. The getDataSource method of \lib\cake\model\ConnectionManager.php prints static::$config, $tmp already exists, as shown in Figure 9
10. Run again, normal, as shown in Figure 10
11. Summary: Why do you need to overwrite setDataSource() in \app\model\appmodel.php, because the database is dynamically obtained from the interface, not from \app\config\database.php, through ConnectionManager::Create, you can create a data source object dynamically.









