【发布时间】:2018-03-03 03:27:54
【问题描述】:
目前我正在 Yii2 框架中开发一个新的网站/平台。
项目存在于多个数据库(不同的客户端/mysql用户帐户)中,每个数据库存在于具有相同结构的多个表中。我知道这违反了关系数据库的指导方针,但由于其他不同的技术原因(不仅仅是懒惰......),不可能更改数据库设置。该数据库也集成在其他程序中,因此不可更改... 此时不需要对数据库进行写入。
所以数据库设置如下:
db_100 --o-- tbl_A1 (tables all have the same structure)
o-- tbl_B2
o-- tbl_C3
db_200 --o-- tbl_A1
o-- tbl_B2
o-- tbl_C3
o-- tbl_D4
db_300 --o-- tbl_A1
...
数据库名和表名总是有相同的前缀,没有定义最大的数据库或表。数据库名和表名的后缀是不可预测的。 (目前 40 db,每个大约 50 个表,但仍在增长)。
因为每个表都有相同的结构,我认为使用 Yii2 框架之外的 ActiveRecord 类是一个好主意。 但是,ActiveRecord 类使用静态方法来获取数据库连接和表名。静态方法无法在为每个实例使用不同的表和数据库时创建类的实例。
getDb() (Yii2 框架)
/**
* Returns the database connection used by this AR class.
* By default, the "db" application component is used as the database connection.
* You may override this method if you want to use a different database connection.
* @return Connection the database connection used by this AR class.
*/
public static function getDb()
{
return Yii::$app->getDb();
}
tableName()(Yii2 框架)
/**
* Declares the name of the database table associated with this AR class.
* By default this method returns the class name as the table name by calling [[Inflector::camel2id()]]
* with prefix [[Connection::tablePrefix]]. For example if [[Connection::tablePrefix]] is `tbl_`,
* `Customer` becomes `tbl_customer`, and `OrderItem` becomes `tbl_order_item`. You may override this method
* if the table is not named after this convention.
* @return string the table name
*/
public static function tableName()
{
return '{{%' . Inflector::camel2id(StringHelper::basename(get_called_class()), '_') . '}}';
}
此时我通过使用请求中的 get-values 使其工作。
所以我可以在 url 中声明表名和数据库,非常简单
http://...:8080/CustomActiveRecord/index?db=100&customTableName=A1
(简化代码)
public static function tableName() {
//get base of tablename
$customTblName = static::customTblName(); //-> Yii::$app->request->get('customTblName') ?: null;
//throw exception if null
if (is_null($customTblName )) {
throw new \yii\web\HttpException(...);
}
//return the tablename
return 'tbl_' . $customTblName;
}
我为 db-connections 做了一些类似的事情(我用所有数据库凭据填充参数数组,并在模型中设置 db 也使用 getDb() 中的 ...request->get(...)功能。
这一切现在都可以与 gridview、listviews、kartik-Chartjs 结合使用……但前提是在 URL 中定义了 tableName 和 db。 这不能同时使用多个模型,这是我需要的。 (比较、统计……)
有人知道如何将一个 ActiveRecord 用于多个表/数据库吗? 理想情况下使用构造函数,以便我可以为每个表创建一个实例?
$model = New CustomActiveRecord(['db' => '100', 'tbl' => 'A1']);
【问题讨论】:
-
看看ActiveQuery,这是
find()静态方法在调用时创建的。 ActiveQuery 允许您选择运行操作的数据库。我快速查看并没有看到传递多个数据库的方法,因此您可能需要在每个数据库上运行查询并将结果合并到一个数组中。 -
我在 ActiveRecord-Model 中尝试了以下操作:
public static function find(){ return new CustomQuery(get_called_class()); }和 CustomQuery(从 \yii\db\ActiveQuery 扩展)我按照方法更新了函数 all() 和 one() (作为测试): public function all($db = null) { $this->from('A1');返回父级::all($db);这已经离我的问题更近了一步,很多查询都知道使用 wright 表,但是像 gridview 这样的小部件仍然使用 ActiveRecord-model 中的静态方法中的 tableName。
标签: php activerecord dynamic yii2