我的项目是基于多租户的。
我有多个客户(公司),每个客户都有多个用户。
每个客户端都有自己的数据库,因此在用户身份验证期间,我会发现该用户的关联数据库的名称。
每个数据库的结构相同......只有数据不同。
这样我们就可以为不同的公司保留不同的数据库,而不会混淆数据库中的数据。
编写应用程序时,未知客户端数量(以及数据库数量),因此无法在引导脚本中包含所有连接。
现在,我想要做的是,动态地改变引导程序中的数据库连接,或者能够为登录的用户动态创建新连接。在Yii中是否有一个简单的解决方案,仍然使用AR,查询构建器?
同样的问题在yii论坛上被问到仍未得到明确答复,.... 你可以在Yii dynamic dabatabase connection
找到这个问题答案 0 :(得分:7)
我和论坛上发布的qiang一样。您需要一个数据库连接列表以及Yii::app()->user
处登录用户的属性,该属性告诉您要使用哪个连接(我为其示例命名为connectionId
)。
然后,您在ActiveRecord基类中覆盖getDbConnection()
:
public function getDbConnection()
{
if(self::$db!==null)
return self::$db;
else
{
// list of connections is an array of CDbConnection configurations indexed by connectionId
$listOfConnections=/* to be loaded somehow */;
// create DB connection based on your spec here:
self::$db=new CDbConnection($listOfConnections[Yii::app()->user->connectionId]);
self::$db->active=true;
return self::$db;
}
}
答案 1 :(得分:3)
感谢您的宝贵帮助,
对于我的应用程序,我需要多个数据库,
a)主数据库,其中包含有关公司的所有信息,称其为'projectmaster'
b)公司sa'company1'的数据库
所以,我在yii \ framework \ db \ ar \ CActiveRecord.php中修改了代码,如下所示,
self::$db=Yii::app()->getDb();
if(self::$db instanceof CDbConnection)
{
$db=Yii::app()->db;
$constring=array();
$constring=$db->createCommand()
->select('dbname,host,dbusername,dbpassword')
->from('projectmaster')
->where('company_name =company1')
->queryRow();
self::$db=new CDbConnection('mysql:host='.$constring['host'].';dbname='.$constring['dbname'],$constring['dbusername'],$constring['dbpassword']);
self::$db->active=true;
return self::$db;
}
这里我使用现有连接创建新的连接对象'self :: $ db', 这是覆盖旧连接还是创建新连接
当我必须使用'createCommand()'来获取某些数据时,我没有使用活动记录类,
所以我的连接对象是时间,
$连接= Yii的::应用程序() - >分贝; $命令= $连接 - > createCommand($ SQL);
这里我正在设置由yii创建的旧连接'$ connection'.... 但对于应用程序,它应该使用新连接,以便从“company1”数据库获取数据。
所以我想创建应该可重用的连接。是否可以更改yiii连接,或者每当我们想要使用自定义查询时,我们都必须重新连接。
答案 2 :(得分:3)
我不确定@Jurish的回答是否及时,但几天前我遇到了完全相同的问题,here就是我解决问题的方法。
简而言之,您应该扩展 CActiveRecord 类,不仅要覆盖 getDbConnection(),还要覆盖类构造函数和 model()函数。
class SuperRecord extends CActiveRecord {
public static $host;
public static $port;
public static $user;
public static $pass;
public static $connection = null;
function __construct($dbName = null, $scenario='insert') {
if ($tenant != null) {
Yii::app()->params['activeDb'] = $dbName;
}
self::$host = Yii::app()->params['defaultDbHost'];
self::$port = Yii::app()->params['defaultDbPort'];
self::$user = Yii::app()->params['superDbUser'];
self::$pass = Yii::app()->params['suPassword'];
parent::__construct($scenario);
Yii::app()->params['activeDb'] = ''; //destruct sensitive data after using
}
public function getDbConnection() {
if(self::$connection!==null)
return self::$connection;
else
{
$connectionString = 'mysql:host='.self::$host.';port='.self::$port.';dbname='.Yii::app()->params['activeDb'];
self::$connection=new CDbConnection($connectionString, self::$user, self::$pass);
self::$connection->emulatePrepare = true;
self::$connection->charset = 'utf8';
self::$connection->active=true;
if(self::$connection instanceof CDbConnection)
return self::$connection;
else
throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.'));
}
}
public static function superModel($dbName, $className=__CLASS__) {
Yii::app()->params['activeDb'] = $dbName;
return self::model($className);
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
之后,您将能够创建连接到数据库的任何模型,您将发送给构造函数的名称,如下所示:
$messagesModel = new UserMessages($databaseName);
或那:
$messages = UserMessages::superModel($databaseName)->findAll();
查看article,我试图尽可能清楚地解释它。
答案 3 :(得分:2)
的Yii ::应用程序() - > DB-> SETACTIVE(假);
Yii :: app() - > db-> connectionString ='mysql:host = localhost; dbname ='。trim($ databasename);
的Yii ::应用程序() - > DB-> SETACTIVE(真);
答案 4 :(得分:0)
搞定了
首先,我有一个名为companyMainDb的主Db,它拥有所有用户信息以及他们的公司ID
每家公司都有不同的数据库,名为 company_company_id
第1步:
Go to web/index.php
第2步:
像这样改变
require(__DIR__ . '/../vendor/autoload.php');
Dotenv::load(__DIR__ . '/../');
// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', getenv('YII_ENV'));
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require(__DIR__ . '/../config/web.php');
new yii \ web \ Application($ config);
的Yii :: $ APP-&GT;用户&GT; isGuest $ DBNAME = 'companyMainDb':?$ DBNAME = '公司_' 的Yii :: $ APP-&GT;用户&GT; identity-&GT; COMPANY_ID; < / p>
$ config ['components'] ['db'] = ['class'=&gt; 'yii \ db \ Connection','dsn' =&GT; 'mysql:host ='。 GETENV( 'DB_HOST')。 '; dbname ='。$ dbName,'username'=&gt; getenv('DB_USER'),'password'=&gt; getenv('DB_PASSWORD'),'charset'=&gt; 'utf8',];
(new yii\web\Application($config))->run();