a7ea550f881d3b1b6e7020936305226d65103526.svn-base 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  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' => '*',
  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. # 验证头部权限
  368. if(isset($this->config['auth']) && is_string($this->config['auth']))
  369. {
  370. $value = isset($param[$this->config['auth_key']]) ? $param[$this->config['auth_key']] : Input::get($this->config['auth_key']);
  371. if($value)
  372. {
  373. $top['value'] = $value;
  374. }
  375. else
  376. {
  377. $top = Load::get('manage/auth.getTop', array($this->config['auth']));
  378. }
  379. if($top)
  380. {
  381. if(!Input::get('where_' . $this->config['auth_key'])) Input::set('where_' . $this->config['auth_key'], $top['value']);
  382. if(!Input::get('option_' . $this->config['auth_key'])) Input::set('option_' . $this->config['auth_key'], $top['value']);
  383. if(!Input::get('set_' . $this->config['auth_key'])) Input::set('set_' . $this->config['auth_key'], $top['value']);
  384. if(!Input::get('add_' . $this->config['auth_key'])) Input::set('add_' . $this->config['auth_key'], $top['value']);
  385. }
  386. }
  387. if($param)
  388. {
  389. if(!is_array($param))
  390. {
  391. $param = array('where_id' => $param, 'option_id' => $param);
  392. }
  393. elseif(is_array($param) && isset($top))
  394. {
  395. if(!isset($param['where_' . $this->config['auth_key']])) $param['where_' . $this->config['auth_key']] = $top['value'];
  396. if(!isset($param['option_' . $this->config['auth_key']])) $param['option_' . $this->config['auth_key']] = $top['value'];
  397. if(!isset($param['set_' . $this->config['auth_key']])) $param['set_' . $this->config['auth_key']] = $top['value'];
  398. if(!isset($param['add_' . $this->config['auth_key']])) $param['add_' . $this->config['auth_key']] = $top['value'];
  399. }
  400. $this->config['param'] =& $param;
  401. }
  402. # 创建全局参数,给hook使用
  403. Config::$global['base']['_param'] = $this->config['param'];
  404. $this->config['response'] = $this->config['request'][$method];
  405. $this->config['input'] = true;
  406. if(isset($this->config['response']['input']))
  407. {
  408. $this->config['input'] = $this->config['response']['input'];
  409. }
  410. $this->push(array('where', 'add', 'set', 'option'))->condition(array('page', 'order', 'limit', 'group'));
  411. $type = isset($this->config['response']['type']) ? $this->config['response']['type'] : $method;
  412. $this->config['response']['col'] = isset($this->config['response']['col']) ? $this->config['response']['col'] : '';
  413. $data = $this->db()->$type($this->config['response']['col']);
  414. $this->hook($method, 'end', $data);
  415. return $data;
  416. }
  417. return array();
  418. }
  419. /**
  420. * hook 插件钩子处理
  421. * @param string $key
  422. *
  423. * @return mixd
  424. */
  425. private function hook($key, $method = 'start', $param = false)
  426. {
  427. # 不再继续执行hook,就设置这个参数
  428. if(Input::get('maze_onload') == 'no')
  429. {
  430. if($method == 'end')
  431. {
  432. Input::set('maze_onload', 'yes');
  433. }
  434. }
  435. elseif(isset($this->config[$method][$key]))
  436. {
  437. # 如果定义了auth,就要传过去
  438. if(isset($this->config['auth']) && is_array($this->config['auth']))
  439. {
  440. $param = array($param, $this->config['auth']);
  441. }
  442. if(is_array($this->config[$method][$key]))
  443. {
  444. foreach($this->config[$method][$key] as $k => $v)
  445. {
  446. Load::get($v, $param);
  447. }
  448. }
  449. else
  450. {
  451. Load::get($this->config[$method][$key], $param);
  452. }
  453. }
  454. }
  455. /**
  456. * push
  457. *
  458. * @return mixd
  459. */
  460. private function push($param)
  461. {
  462. foreach($param as $k => $v)
  463. {
  464. if(isset($this->config['response'][$v]))
  465. {
  466. # 验证传入参数与配置是否相同
  467. /*
  468. $request = Input::prefix($v . '_');
  469. if($v == 'where')
  470. {
  471. $request = Input::prefix('where_');
  472. }
  473. */
  474. $value = array();
  475. foreach($this->config['response'][$v] as $i => $j)
  476. {
  477. $t = array();
  478. if(is_array($j))
  479. {
  480. $t = $j;
  481. $j = $t[0];
  482. }
  483. $temp = $this->request($v. '_' . $i, $j, '', $i, $v);
  484. //if($temp || (($v == 'add' || $v == 'set') && $temp && $temp == 0))
  485. if($temp || ($temp === '0' || $temp === 0))
  486. //if($temp)
  487. {
  488. if(is_array($temp))
  489. {
  490. if(isset($this->config['struct'][$i]) && isset($this->config['struct'][$i]['bit']))
  491. {
  492. $vt = 0;
  493. foreach($temp as $ki => $vi)
  494. {
  495. if(isset($this->config['struct'][$i]['bit'][$vi]))
  496. {
  497. $vt += $this->config['struct'][$i]['bit'][$vi];
  498. }
  499. }
  500. $temp = $vt;
  501. }
  502. elseif(isset($temp[0]) && is_array($temp[0]))
  503. {
  504. $temp = base64_encode(json_encode($temp));
  505. }
  506. else
  507. {
  508. $temp = implode(',', $temp);
  509. }
  510. }
  511. if($temp == 'null')
  512. {
  513. $temp = '';
  514. }
  515. $g = array($i, $temp);
  516. if(isset($t[1]))
  517. {
  518. $g[2] = $t[1];
  519. }
  520. if(isset($t[2]))
  521. {
  522. $g[3] = $t[2];
  523. }
  524. $value[] = $g;
  525. }
  526. }
  527. if($value)
  528. {
  529. if($v == 'option')
  530. {
  531. $v = 'where';
  532. }
  533. $this->db()->$v($value);
  534. }
  535. }
  536. }
  537. return $this;
  538. }
  539. /**
  540. * condition
  541. *
  542. * @return mixd
  543. */
  544. private function condition($param)
  545. {
  546. foreach($param as $k => $v)
  547. {
  548. if(isset($this->config['response'][$v]))
  549. {
  550. if($v == 'page')
  551. {
  552. $value = $this->config['response'][$v];
  553. if(is_string($value[1]))
  554. {
  555. $temp[] = $value[1];
  556. unset($value[1]);
  557. $value[1] = $temp;
  558. }
  559. if(isset($value[2])) $value[1][2] = $value[2];
  560. if(isset($this->config['param']['page']))
  561. {
  562. $value[1] = array_merge($value[1], $this->config['param']['page']);
  563. }
  564. }
  565. else
  566. {
  567. $temp = '';
  568. $value = $this->request($v, $this->config['response'][$v], '-', $temp);
  569. if(!$value)
  570. {
  571. $value = $this->config['response'][$v];
  572. }
  573. }
  574. if(is_string($value))
  575. {
  576. $value = array($value, '');
  577. }
  578. if(empty($value[1])) $value[1] = '';
  579. $this->db()->$v($value[0], $value[1]);
  580. }
  581. }
  582. return $this;
  583. }
  584. /**
  585. * request
  586. *
  587. * @return mixd
  588. */
  589. private function request($key, $value, $split = '', &$index, $method = '')
  590. {
  591. //$index = str_replace(array('add_', 'where_', 'set_', 'option_'), '', $key);
  592. if($index && strpos($value, 'yes-') !== false)
  593. {
  594. $temp = explode('-', $value);
  595. $value = $temp[0];
  596. $index = $temp[1];
  597. }
  598. 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'])
  599. {
  600. if(is_array($this->config['struct'][$index]['match']))
  601. {
  602. $value = $this->config['struct'][$index]['match'][0];
  603. }
  604. else
  605. {
  606. $value = $this->config['struct'][$index]['match'];
  607. }
  608. }
  609. $state = false;
  610. if(isset($this->config['param'][$key]))
  611. {
  612. $request = $this->config['param'][$key];
  613. }
  614. if($value == 'option')
  615. {
  616. $value = '';
  617. $state = true;
  618. }
  619. $callback = is_string($value) && function_exists($value);
  620. if($callback)
  621. {
  622. $callback = $value;
  623. $value = '';
  624. }
  625. if(empty($request))
  626. {
  627. if(isset($request) && $request == 0)
  628. {
  629. return $request;
  630. }
  631. if($this->config['input'])
  632. {
  633. $request = Input::get($key, $value);
  634. }
  635. else
  636. {
  637. $request = $value;
  638. }
  639. }
  640. /*
  641. if(($method == 'set' || $method == 'add') && empty($request) && isset($this->config['struct'][$index]['default']) && $this->config['struct'][$index]['default'])
  642. {
  643. $request = $this->config['struct'][$index]['default'];
  644. }
  645. */
  646. /*
  647. if(is_array($request))
  648. {
  649. $request = implode(',', $request);
  650. }
  651. */
  652. if(is_string($value) && strpos($value, '/') !== false)
  653. {
  654. $state = preg_match($value, $request);
  655. }
  656. elseif(!empty($request))
  657. {
  658. if($callback)
  659. {
  660. $state = $callback($request);
  661. }
  662. elseif(is_string($request) && $split && strpos($request, $split) !== false)
  663. {
  664. $request = explode($split, $request);
  665. }
  666. $state = true;
  667. }
  668. //Debug::log(array('text' => 'model', 'state' => $state, 'preg' => $value, 'key' => $key, 'value' => $request));
  669. if($state)
  670. {
  671. 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)
  672. {
  673. $call = $this->config['struct'][$index]['callback'];
  674. if($call == 'maketime')
  675. {
  676. if(is_string($request))
  677. {
  678. $request = \Maze::maketime($request);
  679. }
  680. }
  681. else
  682. {
  683. $request = $call($request);
  684. }
  685. }
  686. return $request;
  687. }
  688. # error
  689. if($method != 'option' && $method != 'add' && $method != 'set')
  690. {
  691. if(isset($this->config['struct'][$index]['desc']) && $this->config['struct'][$index]['desc'])
  692. {
  693. Output::abert($this->config['struct'][$index]['desc']);
  694. }
  695. else
  696. {
  697. Output::abert('core_database_request', array($key, ($value ? $value : $callback)));
  698. }
  699. }
  700. return false;
  701. }
  702. }