ModelServer.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <?php
  2. namespace app\common\model\base\models;
  3. /**
  4. * @title : 模型代码生成服务
  5. * @desc :
  6. * @Author : Rock
  7. * @Date : 2023-04-18 09:42:34
  8. */
  9. class ModelServer
  10. {
  11. /**
  12. * @title: 删除模型文件
  13. * @desc: 描述
  14. * @param {int} $model_id
  15. * @return {*}
  16. * @author: Rock
  17. * @method: POST
  18. * @Date: 2023-04-23 17:09:42
  19. */
  20. static public function deleteFile(int $model_id = 0)
  21. {
  22. $info = ModelManage::where('id',$model_id)->find();
  23. $name = $info->name;
  24. $classname = self::getCamel($info->name);//获取类名
  25. $dirname = self::parseDirname($info->dirname);// 文件保存位置
  26. if(!empty($dirname)){
  27. $path = root_path()."app".DS."common".DS."model".DS.$dirname.DS;
  28. }else{
  29. $path = root_path()."app".DS."common".DS."model".DS;
  30. }
  31. $filename = $path.$classname.'.php';
  32. if(file_exists($filename)){
  33. @unlink($filename);
  34. }
  35. }
  36. /**
  37. * @title: 生成模型代码
  38. * @desc: 描述
  39. * @param {int} $model_id
  40. * @return {*}
  41. * @author: Rock
  42. * @method: POST
  43. * @Date: 2023-04-23 17:09:54
  44. */
  45. static public function createModelFile(int $model_id=0)
  46. {
  47. $info = ModelManage::where('id',$model_id)->find();
  48. $name = $info->name;
  49. $pk = ModelManage::pk($name);
  50. $dirname = self::parseDirname($info->dirname);// 文件保存位置
  51. $fileTitle = self::createTitle($info->title);//生成文件注释
  52. $fieldList = ModelFields::where('model_name',$name)->where('status',1)->select()->toArray();//获取字段列表
  53. $classname = self::getCamel($info->name);//获取类名
  54. $schema = env('app_debug', false)?'':self::createSchema(array_column($fieldList,'db_type','field'),$pk);// 获取字段数据类型
  55. $attr = self::createAttr($fieldList,$pk);
  56. if(!empty($dirname)){
  57. $path = root_path()."app".DS."common".DS."model".DS.$dirname.DS;
  58. $namespace = "app\common\model\\".str_replace('/','\\',$dirname);
  59. }else{
  60. $path = root_path()."app".DS."common".DS."model".DS;
  61. $namespace = "app\common\model";
  62. }
  63. if(!is_dir($path)){
  64. mkdir($path,0777,true);
  65. }
  66. $filename = $path.$classname.'.php';
  67. $content = <<<PHP
  68. <?php
  69. namespace $namespace;
  70. $fileTitle
  71. use app\common\model\Common;
  72. use think\model\concern\SoftDelete;
  73. class $classname extends Common
  74. {
  75. use SoftDelete;
  76. protected \$name = "$name";
  77. $schema
  78. protected \$pk = "$pk";
  79. $attr
  80. }
  81. PHP;
  82. FileServer::writeLine($filename,$content);
  83. }
  84. /**
  85. * @title: 格式化dir路径
  86. * @desc: 描述
  87. * @param {string} $dirname
  88. * @return {*}
  89. * @author: Rock
  90. * @method: POST
  91. * @Date: 2023-04-24 14:46:37
  92. */
  93. static public function parseDirname(string $dirname)
  94. {
  95. return !empty($dirname)?explode(DS,str_replace(['/','\\'],DS,$dirname))[0]:'';
  96. }
  97. /**
  98. * @title: 根据数据表名生成类名
  99. * @desc: 描述
  100. * @param {string} {name} {} {数据表名}
  101. * @return {*}
  102. * @author: Rock
  103. * @method: POST
  104. * @Date: 2023-04-18 17:09:13
  105. */
  106. static public function getCamel(string $name)
  107. {
  108. $arr = explode('_',$name);
  109. $arr = array_filter($arr);
  110. $classname = "";
  111. foreach($arr as $item){
  112. $classname .= ucfirst($item);
  113. }
  114. return $classname;
  115. }
  116. /**
  117. * @title: 生成模型注释
  118. * @desc: 描述
  119. * @return {*}
  120. * @author: Rock
  121. * @method: POST
  122. * @Date: 2023-04-18 15:13:19
  123. */
  124. static public function createTitle(string $title)
  125. {
  126. $title = <<<EOF
  127. /**
  128. * @title : $title 模型
  129. * @desc :
  130. */
  131. EOF;
  132. return $title;
  133. }
  134. /**
  135. * @title: 生成模型schema属性
  136. * @desc: 描述
  137. * @param {array} $fieldList
  138. * @return {*}
  139. * @author: Rock
  140. * @method: POST
  141. * @Date: 2023-04-18 14:58:27
  142. */
  143. static public function createSchema(array $fieldList,string $pk)
  144. {
  145. $defaultList = [
  146. $pk=>'int',
  147. 'create_at'=>'datetime',
  148. 'update_at'=>'datetime',
  149. 'delete_at'=>'datetime',
  150. ];
  151. $fieldList = array_merge($defaultList,$fieldList);
  152. $str = "[\n";
  153. foreach($fieldList as $field=>$dbtype){
  154. $str.="\t\t'$field'=>'$dbtype',\n";
  155. }
  156. $str = trim($str,",\n");
  157. $str .= "\n ];";
  158. return 'protected $schema = '.$str;
  159. }
  160. /**
  161. * @title: 生成模型关联的获取器
  162. * @desc: 描述
  163. * @param {array} {fieldList} {} {字段列表}
  164. * @return {*}
  165. * @author: Rock
  166. * @method: POST
  167. * @Date: 2023-04-18 17:29:57
  168. */
  169. static public function createAttr(array $fieldList,string $pk)
  170. {
  171. $attr = "";
  172. $append = "protected \$append = [";
  173. foreach($fieldList as $item){
  174. $field = $item['field'];
  175. switch($item['field_type']){
  176. case 'select':
  177. case 'radio':
  178. $camel = self::getCamel($field);
  179. $arrTxt = self::getTxtByContent($item['content']);
  180. $attr.="\tstatic public function ".$camel."List()\n";
  181. $attr.="\t{\n\t\treturn $arrTxt;\n\t}\n";
  182. $attr .= "\tpublic function get".$camel."TxtAttr(\$value,\$row)\n";
  183. $attr .= "\t{\n\t\t\$".$camel."List = self::".$camel."List();\n";
  184. $attr .="\t\treturn \$".$camel."List[\$value ?? \$row['$field']??''] ?? '';\n";
  185. $attr .= "\t}\n";
  186. $append.="'".$field."_txt',";
  187. break;
  188. case 'selects':
  189. case 'checkbox':
  190. $camel = self::getCamel($field);
  191. $arrTxt = self::getTxtByContent($item['content']);
  192. $attr .="\tpublic function set".$camel."Attr(\$value,\$row)\n";
  193. $attr .="\t{\n";
  194. $attr .="\t\treturn implode(',',array_filter(\$value));\n";
  195. $attr .="\t}\n";
  196. $attr .="\tpublic function get".$camel."Attr(\$value,\$row)\n";
  197. $attr .="\t{\n";
  198. $attr .="\t\treturn array_filter(explode(',',\$value));\n";
  199. $attr .="\t}\n";
  200. $attr .="\tstatic public function ".$camel."List()\n";
  201. $attr .="\t{\n\t\treturn $arrTxt;\n\t}\n";
  202. $attr .= "\tpublic function get".$camel."TxtAttr(\$value,\$row)\n";
  203. $attr .= "\t{\n\t\t\$".$camel."List = self::".$camel."List();\n";
  204. $attr .= "\t\t\$value = explode(',',\$row['$field']??'');\n";
  205. $attr .= "\t\t\$res=[];\n";
  206. $attr .= "\t\tforeach(\$value as \$val){\n";
  207. $attr .= "\t\t\t\$res[] = \$".$camel."List[\$val] ?? '';\n";
  208. $attr .="\t\t}\n";
  209. $attr .="\t\treturn array_filter(\$res);\n";
  210. $attr .= "\t}\n";
  211. $append.="'".$field."_txt',";
  212. break;
  213. case 'switch':
  214. $camel = self::getCamel($field);
  215. $extra_rule = $item['extra_rule'];
  216. $active_text = $extra_rule['active_text'];
  217. $inactive_text = $extra_rule['inactive_text'];
  218. $active_value = $extra_rule['active_value'];
  219. $inactive_value = $extra_rule['inactive_value'];
  220. $attr.="\tstatic public function ".$camel."List()\n";
  221. $attr.="\t{\n\t\treturn [$active_value =>'$active_text',$inactive_value=>'$inactive_text'];\n\t}\n";
  222. $attr .= "\tpublic function get".$camel."TxtAttr(\$value,\$row)\n";
  223. $attr .= "\t{\n\t\t\$".$camel."List = self::".$camel."List();\n";
  224. $attr .="\t\treturn \$".$camel."List[\$value ?? \$row['$field']??''] ?? '';\n";
  225. $attr .= "\t}\n";
  226. $append.="'".$field."_txt',";
  227. break;
  228. case 'image':
  229. case 'file':
  230. $camel = self::getCamel($field);
  231. $attr .="\tpublic function set".$camel."Attr(\$value,\$row)\n";
  232. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??'';\n";
  233. $attr .= "\t\treturn !empty(\$value)?str_replace(WEBURL,'',\$value):\$value;\n\t}\n";
  234. $attr .="\tpublic function get".$camel."Attr(\$value,\$row)\n";
  235. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??'';\n";
  236. $attr .= "\t\treturn !empty(\$value)?WEBURL.\$value:'';\n\t}\n";
  237. break;
  238. case 'images':
  239. case 'files':
  240. $camel = self::getCamel($field);
  241. $attr .="\tpublic function set".$camel."Attr(\$value,\$row)\n";
  242. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??[];\n";
  243. $attr .="\t\treturn str_replace(WEBURL,'',implode(',',\$value));\n\t}\n";
  244. $attr .="\tpublic function get".$camel."Attr(\$value,\$row)\n\t{\n";
  245. $attr .="\t\t\$value = \$value??\$row['$field']??'';\n";
  246. $attr .="\t\t\$value = array_filter(explode(',',\$value));\n";
  247. $attr .="\t\tforeach(\$value as &\$val){\n\t\t\t\$val =WEBURL.\$val;\n\t\t}\n";
  248. $attr .="\t\treturn \$value;\n\t}\n";
  249. break;
  250. case 'json':
  251. case 'datetimerange':
  252. case 'daterange':
  253. $camel = self::getCamel($field);
  254. $attr .="\tpublic function set".$camel."Attr(\$value,\$row)\n";
  255. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??[];\n";
  256. $attr .="\t\treturn json_encode(\$value);\n\t}\n";
  257. $attr .="\tpublic function get".$camel."Attr(\$value,\$row)\n";
  258. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??null;\n";
  259. $attr .="\t\treturn !empty(\$value)?json_decode(\$value,true):[];\n\t}\n";
  260. break;
  261. case 'relate_single':
  262. $relationName = $item['relation_model'];
  263. $relationField = $item['relation_field'];
  264. $tbName = explode('_',$relationName);
  265. $lastTbName = end($tbName);
  266. $functionName = $field == $lastTbName.'_id'?self::getCamel($relationName):self::getCamel($field);
  267. $relationInfo = ModelManage::where('name',$relationName)->find();
  268. $namespace = !empty($relationInfo->dirname)?"\app\common\model\\".str_replace('/','\\',self::parseDirname($relationInfo->dirname)):"app\common\model\\";
  269. $relationClass = $namespace.'\\'.self::getCamel($relationName);
  270. $attr .="\tpublic function $functionName()\n";
  271. $attr .="\t{\n\t\treturn \$this->belongsTo($relationClass::class,'$field','$relationField');\n\t}\n";
  272. break;
  273. case 'relate_multiple':
  274. $relationName = $item['relation_model'];
  275. $relationShow = $item['relation_show'];
  276. $functionName = self::getCamel($field);
  277. $relationPk = ModelManage::pk($relationName);
  278. $relationInfo = ModelManage::where('name',$relationName)->find();
  279. $namespace = !empty($relationInfo->dirname)?"\app\common\model\\".str_replace('/','\\',self::parseDirname($relationInfo->dirname)):"app\common\model\\";
  280. $relationClass = $namespace.'\\'.self::getCamel($relationName);
  281. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)\n\t";
  282. $attr .="{\n\t\t\$value = \$value??\$row['$field']??'';\n\t\t";
  283. $attr .="\$value = array_filter(explode(',',\$value));\n\t\t";
  284. $attr .="if(!empty(\$value)){\n\t\t\t\$list = $relationClass::where('$relationPk','IN',\$value)->column('$relationShow');\n\t\t\t";
  285. $attr .="return implode(',',\$list);\n\t\t}else{\n\t\t\treturn '';\n\t\t}\n\t}\n";
  286. $append.="'".$field."_txt',";
  287. $attr .="\tpublic function get{$functionName}Attr(\$value,\$row)\n\t";
  288. $attr .="{\n\t\t\$value = \$value??\$row['$field']??'';\n\t\treturn array_filter(explode(',',\$value));\n\t}\n";
  289. $attr .="\tpublic function set{$functionName}Attr(\$value,\$row)\n\t";
  290. $attr .="{\n\t\t return implode(',',\$value);\n\t}\n";
  291. break;
  292. case 'relate_self':
  293. $relationField = $item['relation_field'];
  294. $functionName = 'Father';
  295. $attr .="\tpublic function Father()\n";
  296. $attr .="\t{\n\t\treturn \$this->belongsTo(self::class,'$field','$relationField');\n\t}\n";
  297. break;
  298. case 'relate_dic':
  299. $functionName = self::getCamel($field);
  300. $relationDicGroup = $item['relation_dic_group'];
  301. $cacheName = 'DIC'.strtoupper($relationDicGroup).'LIST';
  302. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)";
  303. $attr .="\n\t{\n\t\t\$list = cache('$cacheName')??[];";
  304. $attr .="\n\t\tif(empty(\$list)){\n\t\t\t\$list = \app\common\model\base\dic\Dic::where('group_code','$relationDicGroup')->where('status',1)->column('title','code');\n\t\t\tcache('$cacheName',\$list,86400);\n\t\t}";
  305. if(isset($item['extra_rule']['multiple']) && $item['extra_rule']['multiple']===true){
  306. $attr .="\n\t\t\$value = \$value??\$row['$field']??'';";
  307. $attr .="\n\t\t\$arr = explode(',',\$value);";
  308. $attr .="\n\t\t\$TxtArr = [];";
  309. $attr .="\n\t\tforeach(\$arr as \$item){\n\t\t\tif(isset(\$list[\$item])){\n\t\t\t\t\$TxtArr[] = \$list[\$item];\n\t\t\t}\n\t\t}";
  310. $attr .= "\n\t\treturn implode(',',\$TxtArr);\n\t}\n";
  311. $attr .="\tpublic function get{$functionName}Attr(\$value,\$row)\n\t";
  312. $attr .="{\n\t\t\$value = \$value??\$row['$field']??'';\n\t\treturn array_filter(explode(',',\$value));\n\t}\n";
  313. $attr .="\tpublic function set{$functionName}Attr(\$value,\$row)\n\t";
  314. $attr .="{\n\t\t return implode(',',\$value);\n\t}\n";
  315. }else{
  316. $attr .="\n\t\t\$value = \$value??\$row['$field']??'';";
  317. $attr .= "\n\t\treturn isset(\$list[\$value])?\$list[\$value]:'';\n\t}\n";
  318. }
  319. $append.="'".$field."_txt',";
  320. break;
  321. case 'user_auto':
  322. $functionName = self::getCamel($field);
  323. $relationField = $item['relation_field'];
  324. $relationShow = $item['relation_show'];
  325. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)\n";
  326. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??0;\n";
  327. $attr .="\t\treturn \app\common\model\base\user\User::where('$relationField',\$value)->value('$relationShow');\n\t}\n";
  328. $append.="'".$field."_txt',";
  329. $attr .="\tpublic function $functionName()\n";
  330. $attr .="\t{\n\t\treturn \$this->belongsTo(\app\common\model\base\user\User::class,'$field','$relationField');\n\t}\n";
  331. break;
  332. case 'org_auto':
  333. $functionName = self::getCamel($field);
  334. $relationField = $item['relation_field'];
  335. $relationShow = $item['relation_show'];
  336. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)\n";
  337. $attr .="\t{\n\t\t\$value = \$value??\$row['$field']??0;\n";
  338. $attr .="\t\treturn \app\common\model\base\org\Org::where('$relationField',\$value)->value('$relationShow');\n\t}\n";
  339. $append.="'".$field."_txt',";
  340. $attr .="\tpublic function $functionName()\n";
  341. $attr .="\t{\n\t\treturn \$this->belongsTo(\app\common\model\base\org\Org::class,'$field','$relationField');\n\t}\n";
  342. break;
  343. case 'user_select':
  344. $relationShow = $item['relation_show'];
  345. $relationField = $item['relation_field'];
  346. $functionName = self::getCamel($field);
  347. $cacheName = "USERLIST";
  348. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)\n";
  349. $attr .="\t{\n\t\t\$list = cache('$cacheName')??[];\n";
  350. $attr .="\t\t\$value = \$value??\$row['$field']??'';\n";
  351. $attr .="\t\tif(empty(\$list)){\n\t\t\t\$list = \app\common\model\base\user\User::column('name,nickname','user_id');\n\t\t\tcache('$cacheName',\$list,86400);\n\t\t}\n";
  352. if(isset($item['extra_rule']['multiple']) && $item['extra_rule']['multiple']===true){
  353. $attr .="\t\t\$arr = array_filter(explode(',',\$value));\n";
  354. $attr .="\t\t\$TxtArr=[];\n";
  355. $attr .="\t\tforeach(\$arr as \$item){\n\t\t\t\tif(isset(\$list[\$item])){\n\t\t\t\t\$TxtArr[] = \$list[\$item]['$relationShow'];\n\t\t\t}\n\t\t}\n";
  356. $attr .="\t\treturn implode(',',\$TxtArr);\n\t}\n";
  357. $attr .="\tpublic function get{$functionName}Attr(\$value,\$row){\n\t\t\$value = \$value??\$row['$field']??'';\n\t\treturn array_filter(explode(',',\$value));\n\t}\n";
  358. $attr .="\tpublic function set{$functionName}Attr(\$value,\$row)\n\t";
  359. $attr .="{\n\t\t return implode(',',\$value);\n\t}\n";
  360. }else{
  361. $attr .="\t\treturn isset(\$list[\$value])?\$list[\$value]['$relationShow']:'';\n\t}\n";
  362. }
  363. $append.="'".$field."_txt',";
  364. $attr .="\tpublic function $functionName()\n";
  365. $attr .="\t{\n\t\treturn \$this->belongsTo(\app\common\model\base\user\User::class,'$field','$relationField');\n\t}\n";
  366. break;
  367. case 'org_select':
  368. $relationShow = $item['relation_show'];
  369. $relationField = $item['relation_field'];
  370. $functionName = self::getCamel($field);
  371. $cacheName = "ORGLIST";
  372. $attr .="\tpublic function get{$functionName}TxtAttr(\$value,\$row)\n";
  373. $attr .="\t{\n\t\t\$list = cache('$cacheName')??[];\n";
  374. $attr .="\t\t\$value = \$value??\$row['$field']??'';\n";
  375. $attr .="\t\tif(empty(\$list)){\n\t\t\t\$list = \app\common\model\base\org\Org::column('name,short_name','org_id');\n\t\t\t\tcache('$cacheName',\$list,86400);\n\t\t}\n";
  376. if(isset($item['extra_rule']['multiple']) && $item['extra_rule']['multiple']===true){
  377. $attr .="\t\t\$arr = array_filter(explode(',',\$value));\n";
  378. $attr .="\t\t\$TxtArr=[];\n";
  379. $attr .="\t\tforeach(\$arr as \$item){\n\t\t\tif(isset(\$list[\$item])){\n\t\t\t\t\$TxtArr[] = \$list[\$item]['$relationShow'];\n\t\t\t}\n\t\t}\n";
  380. $attr .="\t\treturn implode(',',\$TxtArr);\n\t}\n";
  381. $attr .="\tpublic function get{$functionName}Attr(\$value,\$row)\n\t{\n\t\t\$value = \$value??\$row['$field']??'';\n\t\treturn array_filter(explode(',',\$value));\n\t}\n";
  382. $attr .="\tpublic function set{$functionName}Attr(\$value,\$row)\n\t";
  383. $attr .="{\n\t\t return implode(',',\$value);\n\t}\n";
  384. }else{
  385. $attr .="\t\treturn isset(\$list[\$value])?\$list[\$value]['$relationShow']:'';\n\t}\n";
  386. }
  387. $append.="'".$field."_txt',";
  388. $attr .="\tpublic function $functionName()\n";
  389. $attr .="\t{\n\t\treturn \$this->belongsTo(\app\common\model\base\org\Org::class,'$field','$relationField');\n\t}\n";
  390. break;
  391. default:
  392. break;
  393. }
  394. }
  395. $append = rtrim($append,',');
  396. $append.="];\n";
  397. return $append.$attr;
  398. }
  399. /**
  400. * @title: 将字段的可选项content内容,重组为可写入文件的文本;
  401. * @desc: 描述
  402. * @param {*} $arr
  403. * @return {*}
  404. * @author: Rock
  405. * @method: POST
  406. * @Date: 2023-04-18 17:56:37
  407. */
  408. static public function getTxtByContent($contentArr)
  409. {
  410. if(empty($contentArr)){
  411. return "";
  412. }
  413. $str = "[";
  414. foreach($contentArr as $content){
  415. $key = $content['key'];
  416. $val = $content['value'];
  417. $str .= "'$key'=>'$val',";
  418. }
  419. $str = rtrim($str,',');
  420. $str .= "]";
  421. return $str;
  422. }
  423. }