FieldService.class.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. <?php
  2. namespace Home\Service;
  3. /**
  4. * FieldService
  5. */
  6. class FieldService extends CommonService {
  7. const INDEX_PREFIX = 'idx_';
  8. const UNIQUE_PREFIX = 'uniq_';
  9. /**
  10. * 添加字段
  11. * @param array Field数组
  12. * @return array
  13. */
  14. public function add($field) {
  15. $model = M('Model')->getById($field['model_id']);
  16. $Field = $this->getD();
  17. $Field->startTrans();
  18. $field = $Field->create($field);
  19. // 插入数据
  20. $status = $Field->add($field);
  21. $id = $Field->getLastInsID();
  22. // 添加字段
  23. $ac = $Field->addColumn($model['tbl_name'],
  24. $field['name'],
  25. $field['type'],
  26. $field['length'],
  27. $field['value'],
  28. $field['comment']);
  29. // 字段索引
  30. $idxn = self::INDEX_PREFIX . $field['name'];
  31. if (isset($field['is_index']) && 1 == $field['is_index']) {
  32. $ai = $Field->addIndex($model['tbl_name'], $field['name'], $idxn);
  33. }
  34. // 唯一索引
  35. $uniqn = self::UNIQUE_PREFIX . $field['name'];
  36. if ('' == $field['value']
  37. && isset($field['is_unique'])
  38. && 1 == $field['is_unique']) {
  39. $au = $Field->addUnique($model['tbl_name'], $field['name'],$uniqn);
  40. }
  41. if (false === $status
  42. || false === $ac
  43. || false === $ai
  44. || false === $au) {
  45. // 删除插入数据
  46. $Field->where("id = {$id}")->delete();
  47. // 删除字段
  48. $Field->dropColumn($model['tbl_name'], $field['name']);
  49. $Field->rollback();
  50. return $this->resultReturn(false);
  51. }
  52. $Field->commit();
  53. return $this->resultReturn(true, array('id' => $id));
  54. }
  55. public function just_add_field($field) {
  56. $model = M('Model')->getById($field['model_id']);
  57. $Field = $this->getD();
  58. $field = $Field->create($field);
  59. // 插入数据
  60. $status = $Field->add($field);
  61. $id = $Field->getLastInsID();
  62. return $this->resultReturn(true, array('id' => $id));
  63. }
  64. /**
  65. * 更新字段
  66. * @param array $field
  67. * @return array
  68. */
  69. public function update($field) {
  70. if (!$this->existField($field['id'])) {
  71. return $this->resultReturn(false);
  72. }
  73. $Field = $this->getD();
  74. $old = $Field->getById($field['id']);
  75. // 得到数据表名称
  76. $model = M('Model')->field('tbl_name')->getById($field['model_id']);
  77. $Field->startTrans();
  78. // 更新field
  79. $field = $Field->create($field);
  80. $status = $Field->save($field);
  81. // name
  82. if ($field['name'] != $old['name']
  83. || $field['type'] != $old['type']
  84. || $field['length'] != $old['length']) {
  85. $Field->alterColumnAttr($model['tbl_name'],
  86. $old['name'],
  87. $field['name'],
  88. $field['type'],
  89. $field['length'],
  90. $field['comment']);
  91. }
  92. // value
  93. if ($field['value'] != $old['value']) {
  94. $Field->alterColumnValue($model['tbl_name'],
  95. $field['name'],
  96. $field['value']);
  97. }
  98. // 先删除索引,再进行添加
  99. $oidxn = self::INDEX_PREFIX . $old['name'];
  100. if ($field['is_index'] != $old['is_index']
  101. && 0 == $field['is_index']) {
  102. $Field->dropIndex($model['tbl_name'], $oidxn);
  103. }
  104. $ouniqn = self::UNIQUE_PREFIX . $old['name'];
  105. if ($field['is_unique'] != $old['is_unique']
  106. && 0 == $field['is_unique']) {
  107. $Field->dropIndex($model['tbl_name'], $ouniqn);
  108. }
  109. $idxn = self::INDEX_PREFIX . $field['name'];
  110. if ($field['is_index'] != $old['is_index']
  111. && 1 == $field['is_index']) {
  112. $Field->dropIndex($model['tbl_name'], $oidxn);
  113. $Field->addIndex($model['tbl_name'], $field['name'], $idxn);
  114. }
  115. $uniqn = self::UNIQUE_PREFIX . $field['name'];
  116. if ($field['is_unique'] != $old['is_unique']
  117. && 1 == $field['is_unique']) {
  118. $Field->addIndex($model['tbl_name'], $field['name'], $uniqn);
  119. $Field->dropIndex($model['tbl_name'], $ouniqn);
  120. }
  121. if (false === $status) {
  122. $Field->alterColumnAttr($model['tbl_name'],
  123. $field['name'],
  124. $old['name'],
  125. $old['type'],
  126. $old['length'],
  127. $old['comment']);
  128. $Field->alterColumnValue($model['tbl_name'],
  129. $old['name'],
  130. $old['value']);
  131. (1 == $old['is_index']) ?
  132. $Field->addIndex($model['tbl_name'], $old['name'], $oidxn)
  133. : $Field->dropIndex($model['tbl_name'], $idxn);
  134. $ouniqn = self::UNIQUE_PREFIX . $old['name'];
  135. (1 == $old['is_unique']) ?
  136. $Field->addUnique($model['tbl_name'], $old['name'], $ouniqn)
  137. : $Field->dropIndex($model['tbl_name'], $uniqn);
  138. $Field->rollback();
  139. return $this->resultReturn(false);
  140. }
  141. $Field->commit();
  142. return $this->resultReturn(true);
  143. }
  144. /**
  145. * 删除字段
  146. * @param int $id 需要删除字段的id
  147. * @return array
  148. */
  149. public function delete($id) {
  150. if (!isset($id) || !$this->existField($id)) {
  151. return resultReturn(false);
  152. }
  153. $Field = $this->getD();
  154. $old = $Field->getById($id);
  155. $model = M('Model')->field('tbl_name')->getById($old['model_id']);
  156. $Field->startTrans();
  157. $status = $Field->where("id={$old['id']}")->delete();
  158. // 删除表中的字段
  159. $dcs = $Field->dropColumn($model['tbl_name'], $old['name']);
  160. if (false === $status || false === $dcs) {
  161. $Field->addColumn($model['tbl_name'],
  162. $old['name'],
  163. $old['type'],
  164. $old['length'],
  165. $old['value'],
  166. $old['comment']);
  167. $Field->rollback();
  168. return $this->resultReturn(false);
  169. }
  170. $Field->commit();
  171. return $this->resultReturn(true);
  172. }
  173. /**
  174. * 切换是否列表显示状态
  175. * @param int $id 字段id
  176. * @return boolean
  177. */
  178. public function toggleListShow($id) {
  179. $field = $this->getM()->getById($id);
  180. $field['is_list_show'] = $field['is_list_show'] ? 0 : 1;
  181. return $this->getM()->save($field);
  182. }
  183. /**
  184. * 检查字段名称是否可用
  185. * @param string $name 字段名称
  186. * @param int $model_id 模型id
  187. * @param int $id 需要更新字段的id
  188. * @return array
  189. */
  190. public function checkFieldName($name, $modelId, $id) {
  191. if (!D('Model', 'Service')->existModel($modelId)) {
  192. return $this->errorResultReturn('字段对应的模型不存在!');
  193. }
  194. $Field = $this->getD();
  195. $field['name'] = trim($name);
  196. $field['model_id'] = $modelId;
  197. if ($Field->isValidFieldName($field, $id)) {
  198. return $this->resultReturn(true);
  199. }
  200. return $this->errorResultReturn($Field->getError());
  201. }
  202. /**
  203. * 检查字段标签是否可用
  204. * @param string $name 字段名称
  205. * @param int $modelId 模型id
  206. * @param int $id 需要更新字段的id
  207. * @return array
  208. */
  209. public function checkFieldComment($comment, $modelId, $id) {
  210. if (!D('Model', 'Service')->existModel($modelId)) {
  211. return $this->errorResultReturn('字段对应的模型不存在!');
  212. }
  213. $Field = $this->getD();
  214. $field['comment'] = trim($comment);
  215. $field['model_id'] = $modelId;
  216. if ($Field->isValidFieldComment($field, $id)) {
  217. return $this->resultReturn(true);
  218. }
  219. return $this->errorResultReturn($Field->getError());
  220. }
  221. /**
  222. * 检查字段是否可用
  223. * @param array $field Field数组
  224. * @param int $id 需要更新field的id
  225. * @return mixed
  226. */
  227. public function checkField(&$field, $id) {
  228. // 字段类型约束验证
  229. $result = $this->checkTypeConstraint($field);
  230. if (!$result['status']) {
  231. return $result;
  232. }
  233. if (!D('Model', 'Service')->existModel($field['model_id'])) {
  234. return $this->errorResultReturn('字段对应的模型不存在!');
  235. }
  236. $Field = $this->getD();
  237. if ($Field->isValid($field, $id)) {
  238. return $this->resultReturn(true);
  239. }
  240. return $this->errorResultReturn($Field->getError());
  241. }
  242. /**
  243. * 检查字段type相关的value、length约束
  244. * @param array $field
  245. * @return array
  246. */
  247. public function checkTypeConstraint(&$field) {
  248. switch ($field['type']) {
  249. case 'CHAR':
  250. case 'VARCHAR':
  251. $field['length'] = $field['length']['intchar'];
  252. if (!isset($field['length']) || empty($field['length'])) {
  253. return $this->errorResultReturn('字符串类型长度不能为空!');
  254. }
  255. if (!isint($field['length'])) {
  256. return $this->errorResultReturn('字符串类型长度只能为整数!');
  257. }
  258. break ;
  259. case 'TINYINT':
  260. case 'SMALLINT':
  261. case 'INT':
  262. case 'BIGINT':
  263. $field['length'] = $field['length']['intchar'];
  264. if (!isint($field['length'])) {
  265. return $this->errorResultReturn('整数类型长度只能为整数!');
  266. }
  267. // 默认值只能为整数
  268. if (!empty($field['value']) && !isint($field['value'])) {
  269. return $this->errorResultReturn('整数型默认值只能为有效的整数!');
  270. }
  271. break ;
  272. case 'FLOAT':
  273. case 'DOUBLE':
  274. $realLen = array();
  275. // 长度
  276. if (!empty($field['length']['real'])) {
  277. if (!isint($field['length']['real'])) {
  278. return $this->errorResultReturn('浮点型长度只能为整数!');
  279. }
  280. $realLen[] = $field['length']['real'];
  281. // 精度
  282. if (!empty($field['precision'])) {
  283. if (!isint($field['precision'])) {
  284. return $this->errorResultReturn('浮点型精度只能为整数!');
  285. }
  286. $realLen[] = $field['precision'];
  287. unset($field['precision']);
  288. }
  289. }
  290. // 数据库浮点数形式
  291. $field['length'] = implode(',', $realLen);
  292. // 默认值只能为real
  293. if (!empty($field['value'])
  294. && !is_numeric($field['value'])) {
  295. return $this->errorResultReturn('浮点型默认值只能为有效的数字!');
  296. }
  297. break ;
  298. default:
  299. // mysql支持TEXT长度和默认值
  300. unset($field['length']);
  301. unset($field['value']);
  302. $field['is_index'] = 0;
  303. $field['is_unique'] = 0;
  304. }
  305. unset($field['precision']);
  306. return $this->resultReturn(true);
  307. }
  308. /**
  309. * 重置field长度
  310. * @param array $field
  311. * @return
  312. */
  313. public function resetLength(array &$field) {
  314. switch ($field['type']) {
  315. case 'TINYINT':
  316. case 'SMALLINT':
  317. case 'INT':
  318. case 'BIGINT':
  319. case 'CHAR':
  320. case 'VARCHAR':
  321. $length = $field['length'];
  322. unset($field['length']);
  323. $field['length']['intchar'] = $length;
  324. break ;
  325. case 'FLOAT':
  326. case 'DOUBLE':
  327. $length = explode(',', $field['length']);
  328. unset($field['length']);
  329. $field['length']['real'] = $length[0];
  330. $field['precision'] = $length[1];
  331. break ;
  332. }
  333. }
  334. /**
  335. * 检查字段是否存在
  336. * @param int $fieldId
  337. * @return boolean
  338. */
  339. public function existField($fieldId) {
  340. $m = $this->getM();
  341. if ($m->where("id = {$fieldId}")->count() > 0) {
  342. return true;
  343. }
  344. return false;
  345. }
  346. /**
  347. * 按modelId得到所有字段
  348. * @param int $modelId
  349. * @return array
  350. */
  351. public function getByModelId($modelId, $field) {
  352. return $this->getM()
  353. ->field($field)
  354. ->where("model_id={$modelId}")
  355. ->select();
  356. }
  357. /**
  358. * 按realtion_model得到字段
  359. * @param int $modelId 模型id
  360. * @param string $field 需要的字段
  361. * @return array
  362. */
  363. public function getByRelationModel($modelId, $field) {
  364. return $this->getM()
  365. ->field($field)
  366. ->where("relation_model={$modelId}")
  367. ->select();
  368. }
  369. /**
  370. * 以控制器名得到字段
  371. * @param string $ctrlName 控制器名
  372. * @return array
  373. */
  374. public function getByCtrlName($ctrlName) {
  375. $model = M('Model')->getByTblName(D('Model', 'Service')
  376. ->getTblName($ctrlName));
  377. return $fields = $this->getD()
  378. ->relation(true)
  379. ->where("model_id={$model['id']}")
  380. ->select();
  381. }
  382. /**
  383. * 得到被关联的字段
  384. * @param int $modelId 被关联的模型id
  385. * @param string $fn 被关联的字段名
  386. * @return array
  387. */
  388. public function getRelatedFields($modelId, $fn) {
  389. $where = array('relation_model' => $modelId, 'relation_field' => $fn);
  390. return $this->getD()->relation(true)->where($where)->select();
  391. }
  392. protected function getModelName() {
  393. return 'Field';
  394. }
  395. }