ActiveRecord.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Leo
  5. * Date: 2017/9/3
  6. * Time: 下午9:56
  7. */
  8. namespace common\components;
  9. use common\helpers\snowflake\SnowFake;
  10. use Yii;
  11. use yii\base\ErrorException;
  12. use common\helpers\Date;
  13. use common\helpers\Tool;
  14. use common\models\PerfOrder;
  15. use yii\data\Pagination;
  16. use yii\db\Exception;
  17. use yii\db\Expression;
  18. use yii\db\Migration;
  19. use yii\helpers\ArrayHelper;
  20. /**
  21. * Class ActiveRecord
  22. * @package common\components
  23. */
  24. class ActiveRecord extends \yii\db\ActiveRecord {
  25. /**
  26. * 最后一次执行的SQL
  27. * @var null
  28. */
  29. public static $rawSql = null;
  30. /**
  31. * Query对象
  32. * @var null
  33. */
  34. public static $query = null;
  35. /**
  36. * @var array
  37. */
  38. public static $argv = [];
  39. public function behaviors()
  40. {
  41. $behaviors = parent::behaviors(); // TODO: Change the autogenerated stub
  42. $behaviors[] = \common\behaviors\PrimaryKeyBehavior::class;
  43. return $behaviors;
  44. }
  45. /**
  46. * 重写find方法达到强制使用主库还是从库的问题
  47. * @param bool $enableSlaves
  48. * @param string $fromDb
  49. * @return ActiveQuery
  50. */
  51. public static function find(bool $enableSlaves = false, string $fromDb = '')
  52. {
  53. $modelClass = get_called_class();
  54. if(class_exists($modelClass) && method_exists($modelClass, 'getDb')){
  55. $db = $modelClass::getDb();
  56. $enableSlavesTemp = $db->enableSlaves;
  57. $db->enableSlaves = $enableSlaves;
  58. return \Yii::createObject(ActiveQuery::class, [get_called_class(), ['oriEnableSlaves' => $enableSlavesTemp, 'fromDb' => $fromDb]]);
  59. } else {
  60. return parent::find();
  61. }
  62. }
  63. /**
  64. * 使用主库查询数据
  65. * @return ActiveQuery
  66. */
  67. public static function findUseMaster(){
  68. return self::find(false);
  69. }
  70. /**
  71. * 使用从库查询数据
  72. * @return ActiveQuery
  73. */
  74. public static function findUseSlaves(){
  75. // return self::find(true);
  76. return self::find(false);
  77. }
  78. /**
  79. * 从其他库查询数据
  80. * @param string $fromDb
  81. * @return ActiveQuery
  82. */
  83. public static function findUseOtherDb(string $fromDb){
  84. return self::find(false, $fromDb);
  85. }
  86. /**
  87. * 从奖金专属结算库查询数据
  88. * @return ActiveQuery
  89. */
  90. public static function findUseDbCalc(){
  91. return self::findUseOtherDb('dbCalc');
  92. }
  93. /**
  94. * 以数组的方式获取一条数据
  95. * @param string $condition
  96. * @param array $params
  97. * @param null $select
  98. * @return array|null
  99. */
  100. public static function findOneAsArray($condition='', $params= [], $select=null){
  101. $query = static::find()->where($condition, $params)->asArray();
  102. if($select){
  103. $query->select($select);
  104. }
  105. return $query->one();
  106. }
  107. /**
  108. * 已数组形式获取所有数据
  109. * @param string $condition
  110. * @param array $params
  111. * @param null $select
  112. * @return array|null
  113. */
  114. public static function findAllAsArray($condition='', $params= [], $select=null){
  115. $query = static::find()->where($condition, $params)->asArray();
  116. if($select){
  117. $query->select($select);
  118. }
  119. return $query->all();
  120. }
  121. /**
  122. * 插入一条数据
  123. * @param array $insertData
  124. * @param null $tableName
  125. * @throws Exception
  126. */
  127. public static function insertOne(array $insertData, $tableName = null){
  128. $modelClass = get_called_class();
  129. if($tableName === null){
  130. $tableName = $modelClass::tableName();
  131. }
  132. $db = $modelClass::getDb();
  133. if(!empty($insertData)){
  134. if( !isset($insertData['ID']) ) $insertData['ID'] = SnowFake::instance()->generateId();
  135. if(!$db->createCommand()->insert($tableName, $insertData)->execute()){
  136. throw new Exception($tableName.'表添加一条数据失败');
  137. }
  138. }
  139. }
  140. /**
  141. * 批量添加数据
  142. * @param array $insertData
  143. * @param null $tableName
  144. * @param string $db
  145. * @throws Exception
  146. */
  147. public static function batchInsert(array $insertData, $tableName = null, $db = 'db'){
  148. $modelClass = get_called_class();
  149. if($tableName === null){
  150. $tableName = $modelClass::tableName();
  151. }
  152. if(!empty($insertData)){
  153. $insertKey = [];
  154. foreach($insertData[0] as $key=>$data){
  155. $insertKey[] = $key;
  156. }
  157. if( !in_array('ID', $insertKey ) ) {
  158. array_push($insertKey, 'ID');
  159. foreach ($insertData as & $everyData) {
  160. $everyData['ID'] = SnowFake::instance()->generateId();
  161. }
  162. }
  163. if(!\Yii::$app->$db->createCommand()->batchInsert($tableName, $insertKey, $insertData)->execute()){
  164. throw new Exception($tableName.'表批量添加数据失败');
  165. }
  166. }
  167. }
  168. /**
  169. * 更新全部带着表名
  170. * @param $attributes
  171. * @param string $condition
  172. * @param array $params
  173. * @param null $tableName
  174. * @param string $db
  175. * @return mixed
  176. */
  177. public static function batchUpdate($attributes, $condition = '', $params = [], $tableName = null, $db = 'db') {
  178. $modelClass = get_called_class();
  179. if($tableName === null){
  180. $tableName = $modelClass::tableName();
  181. }
  182. $command = \Yii::$app->$db->createCommand();
  183. $command->update($tableName, $attributes, $condition, $params);
  184. return $command->execute();
  185. }
  186. /**
  187. * @param string $condition
  188. * @param array $params
  189. * @param array $argv
  190. * @param bool $isList
  191. */
  192. public static function prepare($condition = '', $params = [], $argv = [], $isList=false){
  193. $default = [
  194. 'page' => null,
  195. 'pageSize'=>0, //10
  196. 'orderBy'=>'CREATED_AT DESC',
  197. 'with'=>null,
  198. 'select'=>null,
  199. 'asArray'=>true,
  200. 'joinWith'=>null,
  201. 'from'=>null,
  202. 'join'=>null,
  203. 'yearMonth'=>null,
  204. 'useSlaves' => false,
  205. 'count' => '*',
  206. ];
  207. self::$argv = Tool::deepParse($argv ,$default);
  208. if (!self::$argv['pageSize'] && $isList) {
  209. $pageSize = \Yii::$app->request->all('pageSize', \Yii::$app->params['pageSize']);
  210. self::$argv['pageSize'] = $pageSize;
  211. }
  212. if ($condition == '') {
  213. $condition = '1=1';
  214. $params = [];
  215. } else {
  216. $condition = '1=1 ' . $condition;
  217. }
  218. if(self::$argv['useSlaves']){
  219. self::$query = self::findUseSlaves();
  220. } else {
  221. self::$query = self::findUseMaster();
  222. }
  223. if(self::$argv['select']){
  224. self::$query->select(self::$argv['select']);
  225. }
  226. if(self::$argv['with']){
  227. self::$query->with(self::$argv['with']);
  228. }
  229. if(self::$argv['joinWith']){
  230. self::$query->joinWith(self::$argv['joinWith']);
  231. }
  232. if(self::$argv['from']){
  233. self::$query->from(self::$argv['from']);
  234. }
  235. if(self::$argv['yearMonth']){
  236. if(is_array(self::$argv['yearMonth'])){
  237. self::$query->yearMonth(self::$argv['yearMonth'][0], self::$argv['yearMonth'][1]);
  238. } else {
  239. self::$query->yearMonth(self::$argv['yearMonth']);
  240. }
  241. }
  242. if(self::$argv['join']){
  243. if(!is_array(self::$argv['join'][0])){
  244. self::$query->join(self::$argv['join'][0], self::$argv['join'][1], self::$argv['join'][2]);
  245. } else {
  246. foreach(self::$argv['join'] as $value){
  247. self::$query->join($value[0], $value[1], $value[2]);
  248. }
  249. }
  250. }
  251. self::$query->where($condition, $params);
  252. if(self::$argv['orderBy']){
  253. self::$query->orderBy(self::$argv['orderBy']);
  254. }
  255. unset($condition, $params, $argv, $default);
  256. }
  257. /**
  258. * 获取列表
  259. * @param string $condition
  260. * @param array $params
  261. * @param array $argv
  262. * @return array
  263. */
  264. public static function lists($condition = '', $params = [], $argv = []) {
  265. $limit = $argv['limit'] ?? 0;
  266. self::prepare($condition, $params, $argv, true);
  267. unset($condition, $params, $argv);
  268. $countQuery = clone self::$query;
  269. $count = $countQuery->count(self::$argv['count']); // 得到总数
  270. $pagination = new Pagination(['totalCount' => $count]);
  271. $pagination->setPageSize(self::$argv['pageSize']);
  272. if(self::$argv['page'] !== null){
  273. $pagination->setPage(self::$argv['page']);
  274. }
  275. self::$query->offset($pagination->offset)->limit($limit ?: $pagination->limit);
  276. if(self::$argv['asArray']){
  277. self::$query->asArray();
  278. }
  279. $lists = self::$query->all();
  280. self::$query = null;
  281. unset($countQuery);
  282. $startNum = $pagination->page * $pagination->pageSize + 1;
  283. return [
  284. 'list' => $lists ?: [],
  285. 'pagination' => $pagination,
  286. 'currentPage'=>$pagination->page,
  287. 'totalPages'=>$pagination->pageCount,
  288. 'startNum' => $startNum,
  289. 'totalCount' => intval($pagination->totalCount),
  290. 'pageSize' => $pagination->pageSize,
  291. ];
  292. }
  293. /**
  294. * 是否存在某个表
  295. * @param $tableName
  296. * @param string $db
  297. * @return mixed
  298. */
  299. public static function isExistsTable($tableName, $db='db'){
  300. if(preg_match('/^\{\{\%(\w+)\}\}$/', $tableName)){
  301. $tableName = preg_replace('/^\{\{\%(\w+)\}\}$/', \Yii::$app->$db->tablePrefix.'${1}', $tableName);
  302. }
  303. \Yii::$app->$db->getDriverName();
  304. // $table=\Yii::$app->$db->createCommand("select count(*) AS EXI from User_Tables where table_name = '{$tableName}'")->queryOne();
  305. $tableNames = \Yii::$app->$db->getSchema()->getTableNames();
  306. return in_array($tableName, $tableNames);
  307. }
  308. /**
  309. * 删除表
  310. * @param $tableName
  311. * @param string $db
  312. * @return mixed
  313. */
  314. public static function deleteTable($tableName, $db='db'){
  315. return \Yii::$app->$db->createCommand("DROP TABLE {$tableName}")->execute();
  316. }
  317. /**
  318. * 获取表中的所有字段
  319. * @param $modelClassName
  320. * @return array
  321. */
  322. public static function getAllFields($modelClassName){
  323. $table = $modelClassName::tableName();
  324. $tableSchema = \Yii::$app->db->schema->getTableSchema($table);
  325. return $fields = ArrayHelper::getColumn($tableSchema->columns, 'name', false);
  326. }
  327. /**
  328. * 表中是否存在某字段
  329. * @param $modelClassName
  330. * @param $field
  331. * @return bool
  332. */
  333. public static function isExistsField($modelClassName, $field){
  334. $allFields = self::getAllFields($modelClassName);
  335. return in_array($field, $allFields);
  336. }
  337. /**
  338. * 分区表的按月的分区表名
  339. * @param $yearMonth
  340. * @param $format
  341. * @return Expression
  342. */
  343. public static function yearMonthPartName($yearMonth, $format=Date::OCI_TIME_FORMAT_SHORT_MONTH){
  344. $modelClass = get_called_class();
  345. return new Expression($modelClass::tableName()." PARTITION FOR(TO_DATE('$yearMonth'".','."'$format'))");
  346. }
  347. /**
  348. * 通过一张模板表创建一个新的表
  349. * @param $createTableName
  350. * @param $fromTableName
  351. * @param array $indexes
  352. * @param string $creatDb
  353. * @param string $fromDb
  354. */
  355. public static function createTableFromTable($createTableName, $fromTableName, $indexes = [], $creatDb='db', $fromDb='db'){
  356. $fromTableSchema = \Yii::$app->$fromDb->getTableSchema($fromTableName);
  357. if($fromTableSchema){
  358. $mir = new Migration();
  359. $mir->db = \Yii::$app->$creatDb;
  360. $mir->compact = true;
  361. $newColumn = [];
  362. foreach($fromTableSchema->columns as $column){
  363. $tempStr = $column->dbType;
  364. if($column->defaultValue !== null && strtoupper($column->dbType) == 'varchar'){
  365. $tempStr .= ' DEFAULT '."'".trim($column->defaultValue, "'")."'";
  366. } elseif ($column->defaultValue !== null && strtoupper($column->dbType) == 'int') {
  367. $tempStr .= ' DEFAULT '.$column->defaultValue;
  368. }elseif ($column->defaultValue !== null && strtoupper($column->dbType) == 'decimal') {
  369. $tempStr .= ' DEFAULT '.$column->defaultValue;
  370. }
  371. if($column->allowNull){
  372. $tempStr .= '';
  373. } else {
  374. $tempStr .= ' NOT NULL';
  375. }
  376. if($column->isPrimaryKey){
  377. $tempStr .= ' PRIMARY KEY';
  378. }
  379. $newColumn[$column->name] = $tempStr;
  380. unset($tempStr);
  381. }
  382. $mir->createTable($createTableName, $newColumn);
  383. if(!empty($indexes)){
  384. foreach($indexes as $index){
  385. [
  386. 'name' => $name,
  387. 'table' => $table,
  388. 'columns' => $columns,
  389. 'unique' => $unique,
  390. ] = $index;
  391. $unique = $unique ? $unique : false;
  392. $mir->createIndex($name, $table, $columns, $unique);
  393. }
  394. }
  395. }
  396. }
  397. /**
  398. * 删除数据
  399. * @param string $where
  400. * @return bool
  401. */
  402. public static function pageDeleteAll($where='') {
  403. $limit = 10000;
  404. $sql = sprintf('DELETE FROM %s WHERE %s LIMIT %d', strtoupper(self::tableName()), $where, $limit);
  405. $affectRow = self::getDb()->createCommand($sql)->execute();
  406. if( $affectRow == $limit ) {
  407. unset($limit, $sql, $affectRow);
  408. return self::pageDeleteAll($where);
  409. }
  410. unset($limit, $sql, $affectRow);
  411. return true;
  412. }
  413. }