Yii2 自动分表 model
来源:互联网 发布:tensorflow 人脸比对 编辑:程序博客网 时间:2024/05/17 20:35
其实是借鉴了一下某同学的《动态model》
<?php/** * Created by IntelliJ IDEA. * User: Septan * Date: 2017/8/4 * Time: 下午5:25 */namespace app\library;use Yii;use yii\base\InvalidCallException;use yii\base\InvalidConfigException;use yii\db\ActiveQuery;use yii\db\Exception;use yii\helpers\ArrayHelper;/** * 分表基础类 * Class Modelx * @package library */class Modelx extends \yii\db\ActiveRecord{ //原始表名,表结构母版 protected static $originalName = ''; //动态表名 protected static $tableName = ''; //分表关键字 protected static $targetKey = ''; //redis表名set key protected static $tableSetKey = ''; /** * @param null $targetKey * @param array $config * @throws Exception */ public function __construct($targetKey = null, $config = []){ parent::__construct($config); static::$tableName = static::renderTable($targetKey); } public static function tableName(){ return static::$tableName; } /** * 根据关键值获得表名 * @throws Exception * @return string */ public static function getTableName(){ throw new Exception(get_called_class() . "::" . __FUNCTION__ . ' must be override'); //return static::$originalName . '_'. (static::$targetKey % 10); } /** * 根据vip_card探测表名 * @param null $targetKey * @return string * @throws Exception */ public static function renderTable($targetKey = null){ if(!$targetKey) return static::$originalName; static::$targetKey = $targetKey; $tableName = static::getTableName(); //if hit cache /** @var \Redis $redis */ $redis = Yii::$app->redis; if($redis->sismember(static::$tableSetKey, $tableName)) return $tableName; //if hit db $db = static::getDb(); if($db->createCommand("SHOW TABLES LIKE '{$tableName}'")->queryAll()){ $redis->sadd(static::$tableSetKey, $tableName); return $tableName; }else{ //maybe $redis->srem(static::$tableSetKey, $tableName); } //just do it $originalTable = static::$originalName; $createTableRet = $db->createCommand("SHOW CREATE TABLE `{$originalTable}`")->queryOne(); $createTable = str_replace("`{$originalTable}`","`{$tableName}`",$createTableRet['Create Table']); $createTable = preg_replace('/\sAUTO_INCREMENT=\d+/','',$createTable); try{ $db->createCommand($createTable)->execute(); $redis->sadd(static::$tableSetKey, $tableName); }catch (Exception $ex){ throw new Exception("Error execute sql: {$createTable}"); } return $tableName; } /** * 扩展的find * @param $targetKey * @return \yii\db\ActiveQuery */ public static function findx($targetKey = null){ static::$tableName = static::renderTable($targetKey); return Yii::createObject(ActiveQuery::className(), [get_called_class(), ['from' => [static::tableName()]]]); } /** * 扩展的findAll * @param null $targetKey * @param array $params * @return \yii\db\ActiveQuery[] */ public static function findAllx($targetKey = null,$params = []){ return static::findByConditionx($targetKey, $params)->all(); } /** * @Override * @param array $row * @return static */ public static function instantiate($row){ return new static(static::$targetKey); } /** * 禁止使用findBySql * @param string $sql */ public static function findBySql($sql){ throw new InvalidCallException("not allowed. {$sql}"); } /** * 扩展的findOne * @param null $targetKey * @param array $condition * @return null|static|ActiveQuery */ public static function findOnex($targetKey = null, $condition = []){ return static::findByConditionx($targetKey, $condition)->one(); } /** * 内部实现 * @param null $targetKey * @param $condition * @return ActiveQuery[]|ActiveQuery * @throws InvalidConfigException */ protected static function findByConditionx($targetKey = null, $condition){ $query = static::findx($targetKey); 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); }}
分表model
<?phpnamespace app\models;use Yii;use app\library\Modelx;/** * Test 根据vip_card分表实现 * Class Test * @package app\models * @use $m = new Test($vip_card); * @use Test::findx($vip_card)->where([]); * @use Test::findAllx($vip_card,[]); * @use Test::findOnex($vip_card,[]); * */class Test extends Modelx{ //原始表名,表结构母版 protected static $originalName = 'test'; //redis表名set key protected static $tableSetKey = 'project:tableset'; /** * 根据分表关键值获得表名 * @Override * @return string */ public static function getTableName(){ return static::$originalName . '_'. (static::$targetKey % 10); }}
分表使用原始表为模板进行结构复制,复制后的分表结构,不会同步原始表的结构、索引等改变。
建议在分表使用之前,对原始表做好充分优化。
分表之后的Model,不再支持findBySql方法。
阅读全文
0 0
- Yii2 自动分表 model
- Yii2用Gii自动生成Module+Model+CRUD
- Yii2用Gii自动生成Module+Model+CRUD
- Yii2详解Model类
- Yii2—模型(Model)
- yii2 model validate
- yii2 model fields使用说明
- yii2 model 输出sql
- Yii2 - 06模型(Model)
- yii2 常见model操作方法
- Yii2—模型(Model)
- Yii2.0 model基本操作(连表操作)
- Yii2.0-advanced-5—行为的使用(自动生成model时间数据)
- 自动分表--EXCEL
- 自动分表
- Yii2学习-关于Model总结
- Yii2-数据库分表, id 统一生成方法
- [系分] Domain Model
- jQuery NaN isNan() 数字值
- cef下加载flash
- 每日MySQL之010:导出Delimited-Text格式文件
- 7月份月报总结
- Android SDcard 文件读写,RandomAccessFile操作
- Yii2 自动分表 model
- Storm学习之Trident:笔记(一)聚合操作
- js面试常考算法
- 解决recycleview动态添加条目后,item上的edit输入数据造成的数据错乱
- 一个demo学会js
- android jni 用c++使用opengles和egl实现离屏渲染
- 开博啦~~ 算法服务平台-10001
- 正则表达式
- iOS TextView输入长度限制 设置placeholder