动态AR,不用每个表都建model啦 [ 2.0 版本 ]
业务中有时候有这种情况出现,有些数据表是动态生成的,这时候如果有一个动态AR可以使用,这真是极好的。在网上搜了一圈,只有github上yii2的issue里,有人提供了一些思路,我就沿着这个思路进行了一些完善,代码如下:
<?php
namespace app\models;
use Yii;
use yii\base\InvalidConfigException;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
class Mar extends ActiveRecord
{
public static $table = '';
/**
* Mar constructor.
* @param array $table
* @param array $config
*/
public function __construct($table, $config = [])
{
self::$table = $table;
parent::__construct($config);
}
/**
* @return array|string
*/
public static function tableName()
{
return self::$table;
}
// public function rules()
// {
// return [
// ];
// }
//
// public function attributeLabels()
// {
// return [
// ];
// }
/**
* @param $table
* @return object
* @throws InvalidConfigException
*/
public static function findx($table)
{
if (self::$table != $table) {
self::$table = $table;
}
return Yii::createObject(ActiveQuery::className(), [get_called_class(), ['from' => [static::tableName()]]]);
}
/**
* @param array $row
* @return static
*/
public static function instantiate($row)
{
return new static(static::tableName());
}
/**
* @param $table
* @param $condition
* @return mixed
* @throws InvalidConfigException
*/
public static function findOnex($table, $condition)
{
return static::findByConditionx($table, $condition)->one();
}
/**
* @param $table
* @param $condition
* @return mixed
* @throws InvalidConfigException
*/
public static function findAllx($table, $condition)
{
return static::findByConditionx($table, $condition)->all();
}
/**
* @param $table
* @param $condition
* @return mixed
* @throws InvalidConfigException
*/
protected static function findByConditionx($table, $condition)
{
$query = static::findx($table);
if (!ArrayHelper::isAssociative($condition)) {
// query by primary key
$primaryKey = static::primaryKey();
if (isset($primaryKey[0])) {
$condition = [$primaryKey[0] => $condition];
} else {
throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
}
}
return $query->andWhere($condition);
}
}
其中,rules()方法、attributeLabels()方法、search()方法我没有去实现,这块可以动态实现,需要看情况而定。
目前这个完成度,可以实现
$user = new Mar('user');
$user->username = 'xxx';
$user->save()
$user = Mar::findx('user')->where(['id' => 1])->one();
$user = Mar::findOnex('user', 1);
这些基本操作已经都实现了,其中'user'就是动态表名。
暂时我是这么实现的,发出来让大家乐呵乐呵。
tisswb
注册时间:2011-06-24
最后登录:2023-04-10
在线时长:46小时1分
最后登录:2023-04-10
在线时长:46小时1分
- 粉丝28
- 金钱2865
- 威望200
- 积分5325
热门源码
- 基于 Yii 2 + Bootstrap 3 搭建一套后台管理系统 CMF
- 整合完 yii2-rbac+yii2-admin+adminlte 等库的基础开发后台源码
- 适合初学者学习的一款通用的管理后台
- yii-goaop - 将 goaop 集成到 Yii,在 Yii 中优雅的面向切面编程
- yii-log-target - 监控系统异常且多渠道发送异常信息通知
- 店滴云1.3.0
- 面向对象的一小步:添加 ActiveRecord 的 Scope 功能
- Yii2 开源商城 FecShop
- 基于 Yii2 开发的多店铺商城系统,免费开源 + 适合二开
- leadshop - 基于 Yii2 开发的一款免费开源且支持商业使用的商城管理系统
共 14 条评论
不错,谢谢分享 了
能有用就行
支持支持~~~~
妙不可言。。
赞。。。。。。
为啥不能生成表的时候顺便把模型也生成了。
有时候有些动态生成的表 每一个都重复生成model没有必要,还有些时候 比如集成一些第三方的系统,比如我就做过yii2将phpcms作为一个模块嵌入进来的项目,这时,这个类的作用就体现出来了
赞一个,有这个是不是就可以跟TP里面的M方法一样了
可以这么认为,不过还是推荐原生态的一个表对应一个model
@tisswb 我也是这么觉得
不错,很好的拓展思路。
不错!感谢分享!
动态表思路简单,要是动态字段怎么个思路
你的意思是根据不同的字段动态生成表?还是某个字段是个动态的类型?
表单字段由客户自己定义(数量,类型,限制规则)。
@搞搞的传奇 可以参考phpcms的模型概念来实现一遍。
楼主你好,我完全按你的代码打的,可是出了这个错误"Missing argument 1 for app\models\Bb::construct(), called in /var/www/html/yii222/basic/controllers/BbController.php on line 73 and defined",那个"construct"函数重载,需要输入3个参数, 可以看这个帖子有类似问题http://www.yiiframework.com/forum/index.php/topic/70587-missing-argument-2-for-yiibasecontroller-construct/ ; 请问怎么解决阿?
我这边测试了一下,没发现这个错误,请问你的用法是按照我帖子里写的方法使用的么?第一个argument应该是动态的表名,你是不是没写这个?
我有5个结构相同的表,就名字不同,在tablename里hardcode返回不同表命没问题,但是这里我是写的动态表名,model里的php也是完全按这个方法写的,只是我在control里的index下调用,一调用就出错. index 如下:
public function actionIndex() { // $mybb = new Bb('bb'); $dataProvider = new ActiveDataProvider([ 'query' =>Bb::find(), // 'query' => $mybb->find(), ]); return $this->render('index', [ 'dataProvider' => $dataProvider, ]); }
把注释的一取消就会出错,好像是什么ActiveDataProvider里面会调用原来默认的构造函数,但被我们重载了,找不到第一个参数,这种该怎么解决阿,多谢~~~~
@hypermoon 试试如下:
'query' =>Bb::findx('bb')
@tisswb 谢谢,把那个"instantiate"注释掉,就解决了.
@hypermoon 这样啊,我得仔细再看看代码,可能有些冲突,谢谢你的使用
得到启发,非常感谢分享!
我错了 哈哈哈哈
请问 为什么这个方法instantiate() 要传一个$row呢?
我在作者代码的基础上添加了rules()方法、attributeLabels()方法,希望大家指正哈。
地址:https://xiejindou.com/2018/09/27/Yii2动态AR模型/
你这个操作 真是棒棒哒