在 PHP 7.0.22、CakePHP 2.10.3 下,报错:Error: The datasource configuration tmp was not found in database.php.的解决(动态设置数据源对象)
1、在 PHP 7.0.22、CakePHP 2.10.3 下,报错:Error: The datasource configuration tmp was not found in database.php.,如图1
2、打印 $this->useDbConfig,其值为 tmp,如图2
3、确定在 database.php 中不存在 $tmp,如图3
4、但是之前在 CakePHP 2.6.4 确定是正常的,决定对比一下区别,发现区别所在(注:修改了核心库,升级之后,核心库的 _init() 被还原),如图4
\lib\Cake\Model\ConnectionManager.php
1 2 3 4 5 6 7 8 9 | <?php protected static function _init() { // @include_once APP . 'Config' . DS . 'database.php'; // if (class_exists('DATABASE_CONFIG')) { // self::$config = new DATABASE_CONFIG(); // } self:: $_init = true; } ?> |
注:修改了核心库,升级之后,核心库的 _init() 被还原
1 2 3 4 5 6 7 8 9 10 | <?php protected static function _init() { include_once CONFIG . 'database.php' ; if ( class_exists ( 'DATABASE_CONFIG' )) { static :: $config = new DATABASE_CONFIG(); } static :: $_init = true; } ?> |
5、在 \lib\Cake\Model\ConnectionManager.php的getDataSource方法打印static::$config,如图5
6、打印结果,确定不存在 $tmp,如图6
7、现在的需求应该为,在不修改核心库的前提下,确保 static::$config 中存在 $tmp,查看之前的实现,如图7
\app\Model\AppModel.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <?php public function getDbConfig( $tenantid ){ if (! $conn = Cache::read( $tenantid , '_cake_config_' )){ $tenant = new Tenant(); $conn = $tenant ->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 { $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、在运行时以给定的名称和设置动态创建一个DataSource对象,便无需修改核心库,如图8
\app\Model\AppModel.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?php public function getDbConfig( $tenantid ){ if (! $conn = Cache::read( $tenantid , '_cake_config_' )){ $tenant = new Tenant(); $conn = $tenant ->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 { $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、在 \lib\Cake\Model\ConnectionManager.php的getDataSource方法打印static::$config,$tmp已经存在,如图9
10、再次运行,正常,如图10
11、总结:为何需要在 \app\Model\AppModel.php 覆盖 setDataSource(),原因在于数据库是动态从接口获取的,并非源于 \app\Config\database.php,通过 ConnectionManager::create,便可以实现动态创建一个数据源对象。
近期评论