e496de3cd38198c2a98281767f1630623bfd50d9.svn-base 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. <?php namespace Maze\Data;
  2. use Maze\Debug\Process as Debug;
  3. use Maze\Config\Load as Config;
  4. use Maze\Http\Output;
  5. use Maze\Http\Input;
  6. use Maze\Routing\Load;
  7. class Model
  8. {
  9. /**
  10. * database
  11. *
  12. * @var array
  13. */
  14. protected $database;
  15. /**
  16. * config
  17. *
  18. * @var array
  19. */
  20. protected $config;
  21. /**
  22. * db
  23. *
  24. * @var Object
  25. */
  26. protected $db;
  27. /**
  28. * __construct
  29. *
  30. * @return mixd
  31. */
  32. public function __construct($config)
  33. {
  34. $this->config =& $config;
  35. $this->database = Config::get('database', $config['project']);
  36. }
  37. /**
  38. * db
  39. *
  40. * @return mixd
  41. */
  42. protected function db($key = '')
  43. {
  44. if(!$key)
  45. {
  46. $key = isset($this->config['project']) ? $this->config['project'] : MAZE_PROJECT_NAME;
  47. }
  48. if(empty($this->database[$key]))
  49. {
  50. if(empty($this->database['default']))
  51. {
  52. Output::abert('core_database_exists', $key);
  53. }
  54. $this->database[$key] = $this->database['default'];
  55. }
  56. if(empty($this->db[$key]))
  57. {
  58. //$this->config['name'] = $key . '_' . $this->config['name'];
  59. $method = 'Maze\\Data\\' . ucwords($this->database[$key]['type']) . '\\Store';
  60. $this->db[$key] = new $method($this->database[$key]);
  61. $this->db[$key]->table($key . '_' . $this->config['name']);
  62. # 建表
  63. if(isset($this->config['struct']))
  64. {
  65. $create = $this->db[$key]->create($this->config['struct']);
  66. if($create === true)
  67. {
  68. # 写入默认值
  69. if(isset($this->config['default']))
  70. {
  71. $this->db[$key]->inserts($this->config['default']);
  72. }
  73. }
  74. else
  75. {
  76. if(isset($create['struct']))
  77. {
  78. if(count($create['struct']) < count($this->config['struct']))
  79. {
  80. $alter = array_diff_key($this->config['struct'], $create['struct']);
  81. if($alter)
  82. {
  83. $this->db[$key]->alter($alter, $this->config['struct']);
  84. }
  85. }
  86. }
  87. # 更改表结构
  88. if(isset($this->config['alter']))
  89. {
  90. $this->db[$key]->alter($this->config['alter']);
  91. }
  92. }
  93. # 建立索引
  94. if(isset($this->config['index']))
  95. {
  96. $this->db[$key]->index($this->config['index']);
  97. }
  98. }
  99. }
  100. return $this->db[$key];
  101. }
  102. /**
  103. * 获取匹配的类型
  104. *
  105. * @return mixd
  106. */
  107. private function type($method)
  108. {
  109. switch($method)
  110. {
  111. case 1:
  112. $method = '=';
  113. break;
  114. case 2:
  115. $method = 'like';
  116. break;
  117. case 3:
  118. $method = '>';
  119. break;
  120. case 4:
  121. $method = '>=';
  122. break;
  123. case 5:
  124. $method = '<';
  125. break;
  126. case 6:
  127. $method = '<=';
  128. break;
  129. }
  130. return $method;
  131. }
  132. /**
  133. * # 初始化默认方法one、list、update、insert、delete、total、all、check
  134. *
  135. * @return mixd
  136. */
  137. private function init($method, $param = array())
  138. {
  139. $array = array();
  140. $type = '';
  141. $this->config['request'][$method] = array
  142. (
  143. 'type' => $method,
  144. 'where' => array('id' => 'yes'),
  145. );
  146. # 支持单独字段更新
  147. $key = '';
  148. if(strpos($method, 'update_') !== false)
  149. {
  150. $key = str_replace('update_', '', $method);
  151. if($key && isset($this->config['struct'][$key]))
  152. {
  153. $match = $this->config['struct'][$key]['match'];
  154. if(is_array($this->config['struct'][$key]['match']))
  155. {
  156. $match = $this->config['struct'][$key]['match'][0];
  157. }
  158. $this->config['request'][$method]['type'] = 'update';
  159. $this->config['request'][$method]['set'][$key] = $match;
  160. $this->config['request'][$method]['where']['id'] = 'yes';
  161. return;
  162. }
  163. }
  164. switch($method)
  165. {
  166. case 'one':
  167. case 'delete':
  168. break;
  169. case 'updatemul':
  170. #批量更新操作,仅仅开启了mul_type配置或者后台可用
  171. if(isset(Config::$global['base']['mul_type']) && Config::$global['base']['mul_type'] > 0)
  172. {
  173. $this->config['request'][$method]['type'] = 'update';
  174. if(Config::$global['base']['mul_type'] == 2)
  175. {
  176. unset($this->config['request'][$method]['where']);
  177. $type = 'option';
  178. }
  179. else
  180. {
  181. $type = 'mul';
  182. $this->config['request'][$method]['where']['id'] = array('yes', 'in');
  183. }
  184. }
  185. break;
  186. case 'update':
  187. $type = 'set';
  188. $this->config['request'][$method]['input'] = false;
  189. break;
  190. case 'insert':
  191. $this->config['request'][$method]['input'] = false;
  192. unset($this->config['request'][$method]['where']);
  193. $type = 'add';
  194. break;
  195. case 'state':
  196. $this->config['request']['state'] = array
  197. (
  198. 'type' => 'one',
  199. 'where' => array
  200. (
  201. 'state' => 1,
  202. 'id' => 'yes'
  203. )
  204. );
  205. break;
  206. case 'list':
  207. $type = 'option';
  208. $this->config['request']['list'] = array
  209. (
  210. 'type' => 'all',
  211. 'order' => array('id', 'desc'),
  212. 'page' => array(15, 'list'),
  213. 'col' => '*|id',
  214. 'option' => array(),
  215. );
  216. if(isset($this->config['manage']['list_type']) && $this->config['manage']['list_type'] == 'parent')
  217. {
  218. $this->config['request']['list']['page'][0] = 500;
  219. }
  220. if(isset(Config::$global['base']['excel']))
  221. {
  222. unset($this->config['request']['list']['page']);
  223. }
  224. break;
  225. case 'all':
  226. $type = 'option';
  227. $this->config['request']['all'] = array
  228. (
  229. 'type' => 'all',
  230. 'order' => array('id', 'desc'),
  231. 'col' => '*|id',
  232. 'where' => array
  233. (
  234. 'state' => 1,
  235. ),
  236. 'option' => array(),
  237. 'input' => false,
  238. );
  239. break;
  240. case 'check':
  241. $type = 'option';
  242. $this->config['request']['check'] = array
  243. (
  244. 'type' => 'one',
  245. 'col' => '*',
  246. 'where' => array
  247. (
  248. 'state' => 1,
  249. ),
  250. 'option' => array(),
  251. 'input' => false,
  252. );
  253. break;
  254. case 'total':
  255. $type = 'option';
  256. $this->config['request']['total'] = array
  257. (
  258. 'type' => 'all',
  259. 'col' => 'count(*) as total',
  260. 'group' => array('month'),
  261. 'option' => array(),
  262. );
  263. break;
  264. default:
  265. unset($this->config['request'][$method]);
  266. break;
  267. }
  268. if($type)
  269. {
  270. if($type == 'option')
  271. {
  272. $param['search_type'] = isset($param['search_type']) ? $param['search_type'] : Input::get('search_fulltext_type', 1);
  273. $param['search_type'] = $this->type($param['search_type']);
  274. }
  275. foreach($this->config['struct'] as $k => $v)
  276. {
  277. if(isset($v['match']))
  278. {
  279. # 这里增加value,用以区分update/select的值
  280. if(is_array($v['match']))
  281. {
  282. $v['value'] = $v['match'][1];
  283. $v['match'] = $v['match'][0];
  284. }
  285. else
  286. {
  287. $v['value'] = $v['match'];
  288. }
  289. # 首先匹配批量更新
  290. if($method == 'updatemul' && isset($v['update']) && $v['update'] == 'radio' && (is_array($v['option']) || is_object($v['option'])))
  291. {
  292. $this->config['request'][$method]['set'][$k] = $v['value'];
  293. }
  294. if($type == 'option')
  295. {
  296. # 位运算
  297. if(isset($v['bit']))
  298. {
  299. $this->config['request'][$method][$type][$k] = array('option', '&');
  300. }
  301. # 默认排序
  302. elseif(isset($v['order']))
  303. {
  304. if(isset($this->config['request'][$method]['order']))
  305. {
  306. if($this->config['request'][$method]['order'][0] && $this->config['request'][$method]['order'][0] != $k)
  307. {
  308. $this->config['request'][$method]['order'][0] = $k . '` '.(is_string($v['order']) ? $v['order'] : 'desc').',`' . $this->config['request'][$method]['order'][0];
  309. }
  310. }
  311. }
  312. # 全文检索
  313. if(isset($v['search']) && strpos($v['search'], 'fulltext') !== false)
  314. {
  315. $this->config['request'][$method][$type][$k] = array('option', $param['search_type']);
  316. }
  317. # 时间区间
  318. elseif(isset($v['search']) && (strpos($v['search'], 'time') !== false || strpos($v['search'], 'date') !== false))
  319. {
  320. $this->config['request'][$method][$type]['start_' . $k] = array('yes-' . $k, '>=');
  321. $this->config['request'][$method][$type]['end_' . $k] = array('yes-' . $k, '<=');
  322. }
  323. else
  324. {
  325. $this->config['request'][$method][$type][$k] = $v['match'];
  326. }
  327. }
  328. elseif($type != 'mul' && !isset($v['table']))
  329. {
  330. if(!empty($v['insert']) && $type == 'set')
  331. {
  332. }
  333. else
  334. {
  335. $this->config['request'][$method][$type][$k] = $v['value'];
  336. }
  337. }
  338. }
  339. }
  340. }
  341. //print_r($_POST);die;
  342. //print_r($this->config['request'][$method]);die;
  343. }
  344. /**
  345. * method
  346. *
  347. * @return mixd
  348. */
  349. public function method($method = 'one', $param = array())
  350. {
  351. if(isset($param[0]) && is_array($param[0]))
  352. {
  353. $result = array();
  354. foreach($param as $k => $v)
  355. {
  356. $result[] = $this->method($method, $v);
  357. }
  358. return $result;
  359. }
  360. if(!isset($this->config['request'][$method])) $this->init($method, $param);
  361. //print_r($this->config['request']);die;
  362. $this->config['param'] = array();
  363. if(isset($this->config['request']) && isset($this->config['request'][$method]))
  364. {
  365. $this->hook('request', 'onload');
  366. $this->hook($method, 'start');
  367. if($param && !is_array($param))
  368. {
  369. $param = array('where_id' => $param, 'option_id' => $param);
  370. }
  371. # 验证头部权限
  372. if(isset($this->config['auth']) && is_string($this->config['auth']))
  373. {
  374. $value = isset($param[$this->config['auth_key']]) ? $param[$this->config['auth_key']] : Input::get($this->config['auth_key']);
  375. if($value)
  376. {
  377. $top['value'] = $value;
  378. }
  379. else
  380. {
  381. $top = Load::get('manage/auth.getTop', array($this->config['auth']));
  382. }
  383. if($top)
  384. {
  385. if(!Input::get('where_' . $this->config['auth_key'])) Input::set('where_' . $this->config['auth_key'], $top['value']);
  386. if(!Input::get('option_' . $this->config['auth_key'])) Input::set('option_' . $this->config['auth_key'], $top['value']);
  387. if(!Input::get('set_' . $this->config['auth_key'])) Input::set('set_' . $this->config['auth_key'], $top['value']);
  388. if(!Input::get('add_' . $this->config['auth_key'])) Input::set('add_' . $this->config['auth_key'], $top['value']);
  389. if(!isset($param['where_' . $this->config['auth_key']])) $param['where_' . $this->config['auth_key']] = $top['value'];
  390. if(!isset($param['option_' . $this->config['auth_key']])) $param['option_' . $this->config['auth_key']] = $top['value'];
  391. if(!isset($param['set_' . $this->config['auth_key']])) $param['set_' . $this->config['auth_key']] = $top['value'];
  392. if(!isset($param['add_' . $this->config['auth_key']])) $param['add_' . $this->config['auth_key']] = $top['value'];
  393. }
  394. }
  395. if($param)
  396. {
  397. $this->config['param'] =& $param;
  398. }
  399. # 创建全局参数,给hook使用
  400. Config::$global['base']['_param'] =& $this->config['param'];
  401. $this->config['response'] = $this->config['request'][$method];
  402. $this->config['input'] = true;
  403. if(isset($this->config['response']['input']))
  404. {
  405. $this->config['input'] = $this->config['response']['input'];
  406. }
  407. $this->push(array('where', 'add', 'set', 'option'))->condition(array('page', 'order', 'limit', 'group'));
  408. $type = isset($this->config['response']['type']) ? $this->config['response']['type'] : $method;
  409. $this->config['response']['col'] = isset($this->config['response']['col']) ? $this->config['response']['col'] : '';
  410. $data = $this->db()->$type($this->config['response']['col']);
  411. $this->hook($method, 'end', $data);
  412. return $data;
  413. }
  414. return array();
  415. }
  416. /**
  417. * hook 插件钩子处理
  418. * @param string $key
  419. *
  420. * @return mixd
  421. */
  422. private function hook($key, $method = 'start', $param = false)
  423. {
  424. # 不再继续执行hook,就设置这个参数
  425. if(Input::get('maze_onload') == 'no')
  426. {
  427. if($method == 'end')
  428. {
  429. Input::set('maze_onload', 'yes');
  430. }
  431. }
  432. elseif(isset($this->config[$method][$key]))
  433. {
  434. # 如果定义了auth,就要传过去
  435. if(isset($this->config['auth']) && is_array($this->config['auth']))
  436. {
  437. $param = array($param, $this->config['auth']);
  438. }
  439. if(is_array($this->config[$method][$key]))
  440. {
  441. foreach($this->config[$method][$key] as $k => $v)
  442. {
  443. Load::get($v, $param);
  444. }
  445. }
  446. else
  447. {
  448. Load::get($this->config[$method][$key], $param);
  449. }
  450. }
  451. }
  452. /**
  453. * push
  454. *
  455. * @return mixd
  456. */
  457. private function push($param)
  458. {
  459. foreach($param as $k => $v)
  460. {
  461. if(isset($this->config['response'][$v]))
  462. {
  463. # 验证传入参数与配置是否相同
  464. /*
  465. $request = Input::prefix($v . '_');
  466. if($v == 'where')
  467. {
  468. $request = Input::prefix('where_');
  469. }
  470. */
  471. $value = array();
  472. foreach($this->config['response'][$v] as $i => $j)
  473. {
  474. $t = array();
  475. if(is_array($j))
  476. {
  477. $t = $j;
  478. $j = $t[0];
  479. }
  480. $temp = $this->request($v. '_' . $i, $j, '', $i, $v);
  481. //if($temp || (($v == 'add' || $v == 'set') && $temp && $temp == 0))
  482. if($temp || ($temp === '0' || $temp === 0))
  483. //if($temp)
  484. {
  485. if(is_array($temp))
  486. {
  487. if(isset($this->config['struct'][$i]) && isset($this->config['struct'][$i]['bit']))
  488. {
  489. $vt = 0;
  490. foreach($temp as $ki => $vi)
  491. {
  492. if(isset($this->config['struct'][$i]['bit'][$vi]))
  493. {
  494. $vt += $this->config['struct'][$i]['bit'][$vi];
  495. }
  496. }
  497. $temp = $vt;
  498. }
  499. elseif(isset($temp[0]) && is_array($temp[0]))
  500. {
  501. $temp = base64_encode(json_encode($temp));
  502. }
  503. else
  504. {
  505. $temp = implode(',', $temp);
  506. }
  507. }
  508. if($temp === 'null')
  509. {
  510. $temp = '';
  511. }
  512. $g = array($i, $temp);
  513. if(isset($t[1]))
  514. {
  515. $g[2] = $t[1];
  516. }
  517. if(isset($t[2]))
  518. {
  519. $g[3] = $t[2];
  520. }
  521. $value[] = $g;
  522. }
  523. }
  524. if($value)
  525. {
  526. if($v == 'option')
  527. {
  528. $v = 'where';
  529. }
  530. $this->db()->$v($value);
  531. }
  532. }
  533. }
  534. return $this;
  535. }
  536. /**
  537. * condition
  538. *
  539. * @return mixd
  540. */
  541. private function condition($param)
  542. {
  543. foreach($param as $k => $v)
  544. {
  545. if(isset($this->config['response'][$v]))
  546. {
  547. if($v == 'page')
  548. {
  549. $value = $this->config['response'][$v];
  550. if(is_string($value[1]))
  551. {
  552. $temp[] = $value[1];
  553. unset($value[1]);
  554. $value[1] = $temp;
  555. }
  556. if(isset($value[2])) $value[1][2] = $value[2];
  557. if(isset($this->config['param']['page']))
  558. {
  559. $value[1] = array_merge($value[1], $this->config['param']['page']);
  560. }
  561. }
  562. else
  563. {
  564. $temp = '';
  565. $value = $this->request($v, $this->config['response'][$v], '-', $temp);
  566. if(!$value)
  567. {
  568. $value = $this->config['response'][$v];
  569. }
  570. }
  571. if(is_string($value))
  572. {
  573. $value = array($value, '');
  574. }
  575. if(empty($value[1])) $value[1] = '';
  576. $this->db()->$v($value[0], $value[1]);
  577. }
  578. }
  579. return $this;
  580. }
  581. /**
  582. * request
  583. *
  584. * @return mixd
  585. */
  586. private function request($key, $value, $split = '', &$index, $method = '')
  587. {
  588. //$index = str_replace(array('add_', 'where_', 'set_', 'option_'), '', $key);
  589. if($index && strpos($value, 'yes-') !== false)
  590. {
  591. $temp = explode('-', $value);
  592. $value = $temp[0];
  593. $index = $temp[1];
  594. }
  595. if($index && $value == 'yes' && isset($this->config['struct'][$index]) && is_array($this->config['struct'][$index]) && isset($this->config['struct'][$index]['match']) && $this->config['struct'][$index]['match'])
  596. {
  597. if(is_array($this->config['struct'][$index]['match']))
  598. {
  599. $value = $this->config['struct'][$index]['match'][0];
  600. }
  601. else
  602. {
  603. $value = $this->config['struct'][$index]['match'];
  604. }
  605. }
  606. $state = false;
  607. if(isset($this->config['param'][$key]))
  608. {
  609. $request = $this->config['param'][$key];
  610. }
  611. if($value == 'option')
  612. {
  613. $value = '';
  614. $state = true;
  615. }
  616. $callback = is_string($value) && function_exists($value);
  617. if($callback)
  618. {
  619. $callback = $value;
  620. $value = '';
  621. }
  622. if(isset($request) && ($request === '0' || $request === 0))
  623. {
  624. return 0;
  625. }
  626. if(empty($request))
  627. {
  628. if($this->config['input'])
  629. {
  630. $request = Input::get($key, $value);
  631. }
  632. else
  633. {
  634. $request = $value;
  635. }
  636. }
  637. /*
  638. if(($method == 'set' || $method == 'add') && empty($request) && isset($this->config['struct'][$index]['default']) && $this->config['struct'][$index]['default'])
  639. {
  640. $request = $this->config['struct'][$index]['default'];
  641. }
  642. */
  643. /*
  644. if(is_array($request))
  645. {
  646. $request = implode(',', $request);
  647. }
  648. */
  649. if(is_string($value) && strpos($value, '/') !== false)
  650. {
  651. $state = preg_match($value, $request);
  652. }
  653. elseif(!empty($request))
  654. {
  655. if($callback)
  656. {
  657. $state = $callback($request);
  658. }
  659. elseif(is_string($request) && $split && strpos($request, $split) !== false)
  660. {
  661. $request = explode($split, $request);
  662. }
  663. $state = true;
  664. }
  665. //Debug::log(array('text' => 'model', 'state' => $state, 'preg' => $value, 'key' => $key, 'value' => $request));
  666. if($state)
  667. {
  668. if($index && isset($this->config['struct'][$index]) && is_array($this->config['struct'][$index]) && isset($this->config['struct'][$index]['callback']) && $this->config['struct'][$index]['callback'] && $request)
  669. {
  670. $call = $this->config['struct'][$index]['callback'];
  671. if($call == 'maketime')
  672. {
  673. if(is_string($request))
  674. {
  675. $request = \Maze::maketime($request);
  676. }
  677. }
  678. else
  679. {
  680. $request = $call($request);
  681. }
  682. }
  683. return $request;
  684. }
  685. # error
  686. if($method != 'option' && $method != 'add' && $method != 'set')
  687. {
  688. if(isset($this->config['struct'][$index]['desc']) && $this->config['struct'][$index]['desc'])
  689. {
  690. Output::abert($this->config['struct'][$index]['desc']);
  691. }
  692. else
  693. {
  694. Output::abert('core_database_request', array($key, ($value ? $value : $callback)));
  695. }
  696. }
  697. return false;
  698. }
  699. }