Base.php 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446
  1. <?php
  2. namespace Qii\Driver;
  3. use Qii\Autoloader\Psr4;
  4. use Qii\Exceptions\InvalidFormat;
  5. use Qii\Exceptions\InvalidParams;
  6. use Qii\Exceptions\TableException;
  7. use Qii\Exceptions\Variable;
  8. /**
  9. * Class Base
  10. * @package Qii\Driver
  11. * 使用方法
  12. * class base extends \Qii\Driver\Model {
  13. * public function __construct()
  14. * {
  15. * parent::__construct();
  16. * }
  17. * public function demo()
  18. * {
  19. * $this->db->fields("*")->join(array("leftJoin", array('table' => 'ad_site', 'alias' => 'b', 'on' => 'a.uid = b.uid')))->where(array('a.create_at:greater' => 1))->limit(10)->groupBy(array('a.uid', 'a.create_at'))->orderBy(array('a.uid' => 'desc'))->selectAll('user a');
  20. * $this->db->where(array('uid' => 1))->set(array('create_at:plus' => time(), 'status' => 1))->update('user');
  21. * $this->db->updateObject('user', array('create_at:plus' => time(), 'status' => 1), array('uid' => 1));
  22. * $this->db->where(array('uid:greater' => 1))->delete('user');
  23. * $this->db->deleteObject('user', array('uid' => 1));
  24. * $this->db->where(array('uid:greater' => 1))->like("email like '%test@test.com%'")->selectAll('user');
  25. * $this->db->where(array('uid:greater' => 1))->where("or")->like(array('email' => 'test@testcom'))->selectAll('user');
  26. * $this->db->where(array('uid:greater' => 1, 'or', 'email:like' => 'test@test.com'))->selectAll('user');
  27. * $this->db->where(array('uid:greater' => 1))->where("OR")->like(array('email' => 'test@test.com'))->selectAll('user');
  28. * $this->db->where(array('name' => 'antsnet'))->exclude(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
  29. * $this->db->where(array('name' => 'antsnet'))->orTerms(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
  30. * $this->db->orTerms(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
  31. * $this->db->join(array("leftJoin", array("table" => 'table', 'alias' => 'a', 'on' => 'a.id=b.id')));
  32. * $this->db->join(" LEFT JOIN table c on c.id=a.id")->selectAll('use a');
  33. * $this->db->where(array('email:unequal' => 'test@test.com'))->in(array('uid:in' => array('1,2,3'), 'status' => array(1)))->selectAll('user');
  34. * $this->>db->where(array('uid:in' => '1,2,3', 'email' => 'test@tset.com', 'status' => 1))->selectAll('user');
  35. * $this->db->where(array(array('email:unequal' => 'test@test.com'), array('uid:in' => array('1,2,3'), 'status:in' => array(1))))->selectAll('user');
  36. * }
  37. * }
  38. */
  39. class Base
  40. {
  41. const VERSION = '1.3';
  42. use TraitDatabase;
  43. use TraitCache;
  44. //query 方法
  45. protected $_query = array(
  46. "INSERT" => "INSERT INTO %s(%s) VALUES('%s')",
  47. "REPLACE" => "REPLACE %s (%s) VALUES('%s')",
  48. "SELECT" => "SELECT %s FROM %s %s",
  49. "UPDATE" => "UPDATE %s SET ",
  50. "DELETE" => "DELETE FROM %s %s",
  51. "WHERE" => " WHERE %s",
  52. "OR" => " `%s` = '%s' ",
  53. "ORDER" => " ORDER BY %s %s",
  54. "GROUP" => " GROUP BY %s",
  55. "LIMIT" => " LIMIT %d, %d"
  56. );
  57. //load类
  58. public $load;
  59. //cache类
  60. public $cache;
  61. //语言包
  62. public $language;
  63. //响应内容
  64. public $response;
  65. //执行的sql语句
  66. public $modelSQL = "";
  67. /**
  68. * @var string sql 引用
  69. */
  70. public $executeSQL = '';
  71. public $operateVal = array('or', 'and', 'like');//连接条件操作;
  72. public $shortExpression = array(
  73. 'equal' => "%s`%s` = '%s'",
  74. 'in' => "%s`%s` in (%s)",
  75. 'unequal' => "%s`%s` != '%s'",
  76. 'greater' => "%s`%s` > '%s'",
  77. 'gt' => "%s`%s` > '%s'",
  78. 'greaterEqual' => "%s`%s` >= '%s'",
  79. 'gte' => "%s`%s` >= '%s'",
  80. 'less' => "%s`%s` < '%s'",
  81. 'lessEqual' => "%s`%s` <= '%s'",
  82. 'lte' => "%s`%s` <= '%s'",
  83. 'like' => "%s`%s` like '%%%s%%'"
  84. );
  85. public $operateTable = array('leftJoin', 'rightJoin', 'innerJoin');//链接表的操作
  86. public $faultTolerant = true;
  87. public $whereCondition = array();
  88. public $joinCondition = array();
  89. public $fields = "*";
  90. public $sets = array();
  91. protected $groupBy;
  92. protected $limit;
  93. protected $orderBy;
  94. protected $_modelAlias = array('updateRows' => 'update', 'selectRows' => 'selectAll', 'select' => 'selectRow', 'getOne' => 'selectOne', 'getRow' => 'selectRow', 'getAll' => 'selectAll', 'remove' => 'delete', 'deleteRows' => 'delete');
  95. public function __construct()
  96. {
  97. $this->language = Psr4::getInstance()->loadClass('Qii\Language\Loader');
  98. $this->load = Psr4::getInstance()->loadClass('\Qii\Autoloader\Loader');
  99. $this->response = new Response();
  100. }
  101. /**
  102. * 获取所有数据
  103. *
  104. * @param $table
  105. * @param null $where
  106. * @return mixed
  107. * @throws \Exception
  108. */
  109. public function selectAll($table, $where = null)
  110. {
  111. if(is_array($where) && count($where) > 0)
  112. {
  113. $this->where($where);
  114. }
  115. $sql = $this->createSelectSQL($table);
  116. return $this->getAll($sql);
  117. }
  118. /**
  119. * 返回resource资源
  120. * @param string $table 数据表名称
  121. */
  122. final function rs($table)
  123. {
  124. $sql = $this->createSelectSQL($table);
  125. return $this->setQuery($sql);
  126. }
  127. /**
  128. * 查询一行
  129. * @param $table
  130. * @param null $where
  131. * @return array | bool
  132. * @throws \Exception
  133. */
  134. public function selectRow($table, $where = null)
  135. {
  136. if(is_array($where) && count($where) > 0)
  137. {
  138. $this->where($where);
  139. }
  140. $sql = $this->createSelectSQL($table);
  141. return $this->getRow($sql);
  142. }
  143. /**
  144. * get row 子类去覆写
  145. *
  146. * @param $sql
  147. * @return false
  148. */
  149. public function getRow($sql) {
  150. return false;
  151. }
  152. /**
  153. *
  154. * 查询一列
  155. * @param string $table 表名
  156. * @return false | array
  157. * @throws TableException
  158. */
  159. final function selectOne($table)
  160. {
  161. //验证table是否合法
  162. if (!$this->verifyTable($table)) {
  163. if (gettype($table) == 'string') {
  164. throw new TableException("表名不能包含怪字符且不能以数字开头,获取到的是". $table);
  165. }
  166. throw new TableException("表名必须是字符串加下划线,目标字符为". gettype($table));
  167. }
  168. $sql = $this->createSelectSQL($table);
  169. return $this->getOne($sql);
  170. }
  171. /**
  172. * get one 方法, 子类去覆写
  173. * @param string $sql
  174. * @return false | array
  175. */
  176. public function getOne($sql) {
  177. return false;
  178. }
  179. /**
  180. * 格式化插入值,新增null值插入
  181. *
  182. * @param $arr
  183. * @return array|mixed
  184. */
  185. protected function formatInsertObject($arr) {
  186. if(is_array($arr)) {
  187. $values = array();
  188. foreach ($arr as $val) {
  189. if(strtoupper(gettype($val)) == 'NULL') {
  190. $values[] = 'null';
  191. continue;
  192. }
  193. $values[] = "'". $val . "'";
  194. }
  195. return $values;
  196. }
  197. return $arr;
  198. }
  199. /**
  200. * 插入数据
  201. * @param $table
  202. * @param $dataArray
  203. * @return int
  204. * @throws InvalidFormat
  205. */
  206. final function insertObject($table, $dataArray)
  207. {
  208. if (empty($table)) {
  209. throw new InvalidParams(_i('%s is invalid', 'table'), __LINE__);
  210. }
  211. $replaceObj = $this->createInsertReplaceObj($dataArray);
  212. if(empty($replaceObj['fields']) || empty($replaceObj['values']))
  213. {
  214. throw new Variable(_i('Invalid %s format', 'data'), __LINE__);
  215. }
  216. // 针对 null 值单独处理,并将值的两端加上单引号 '
  217. $values = $this->formatInsertObject($replaceObj['values']);
  218. $this->executeSQL = $this->modelSQL = $sql = "INSERT INTO " . $this->getTable($table) . "(`" . join("`, `", $replaceObj['fields']) . "`) VALUES(". join(',', $values) . ")";
  219. $this->setQuery($sql);
  220. $this->setError();
  221. return $this->lastInsertId();
  222. }
  223. /**
  224. *
  225. * Replace Object
  226. * @param String $table
  227. * @param Array|Object $dataArray
  228. */
  229. final function replaceObject($table, $dataArray)
  230. {
  231. if (empty($table)) {
  232. throw new InvalidParams(_i('%s is invalid', 'table'), __LINE__);
  233. }
  234. $replaceObj = $this->createInsertReplaceObj($dataArray);
  235. if(empty($replaceObj['fields']) || empty($replaceObj['values']))
  236. {
  237. throw new Variable(_i('Invalid %s format', 'data'), __LINE__);
  238. }
  239. // 针对 null 值单独处理,并将值的两端加上单引号 '
  240. $values = $this->formatInsertObject($replaceObj['values']);
  241. $this->executeSQL = $this->modelSQL = $sql = "REPLACE INTO " . $this->getTable($table) . "(`" . join("`, `", $replaceObj['fields']) . "`) VALUES(". join(',', $values) . ")";
  242. $rs = $this->setQuery($sql);
  243. $this->setError();
  244. return $this->AffectedRows($rs);
  245. }
  246. /**
  247. * 创建插入或替换的内容
  248. *
  249. * @param $dataArray
  250. * @return array
  251. * @throws InvalidFormat
  252. */
  253. protected function createInsertReplaceObj($dataArray)
  254. {
  255. if(gettype($dataArray) == 'object') {
  256. $dataArray = get_object_vars($dataArray);
  257. }
  258. if (sizeof($dataArray) > 0) {
  259. $keys = array();
  260. $values = array();
  261. foreach ($dataArray AS $key => $value) {
  262. $keys[] = $key;
  263. if (is_array($value)) {
  264. throw new InvalidFormat(_i('Invalid %s format', $key), __LINE__);
  265. }
  266. if(strtoupper(gettype($value)) == 'NULL') {
  267. $values[] = null;
  268. }else{
  269. $values[] = $this->setQuote($value);
  270. }
  271. }
  272. return array('fields' => $keys, 'values' => $values);
  273. }
  274. return array('fields' => array(), 'values' => array());
  275. }
  276. /**
  277. * 更新表中指定数据 结合set、where等方法是用
  278. *
  279. * @param string $table
  280. * @return string
  281. * @throws \Exception
  282. */
  283. public function update($table)
  284. {
  285. if(!$table) {
  286. throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
  287. }
  288. $set = join(",", $this->sets);
  289. $this->sets = array();
  290. if(count($this->whereCondition) > 0 && $this->isOperator($this->whereCondition[0]))
  291. {
  292. array_shift($this->whereCondition);
  293. }
  294. $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
  295. $this->whereCondition = array();
  296. $alias = $this->getTableAlias($table);
  297. $this->executeSQL = $this->modelSQL = $sql = sprintf($this->_query['UPDATE'], $alias['name'] . $alias['alias']) . $set. $where;
  298. return $this->exec($sql);
  299. }
  300. /**
  301. * 更新表的数据,同时可以使用update方法达到同样的效果
  302. *
  303. * @param $table
  304. * @param $dataArray
  305. * @param array $where [key => $val]
  306. * @return string
  307. * @throws \Exception
  308. */
  309. final function updateObject($table, $dataArray, $where = array()){
  310. if(!$table) {
  311. throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
  312. }
  313. return $this->set($dataArray)->where($where)->update($table);
  314. }
  315. /**
  316. * 删除表中的数据,结合where方法使用
  317. *
  318. * @param string $table 表名
  319. * @return string
  320. * @throws \Exception
  321. */
  322. final function delete($table)
  323. {
  324. if(!$table) {
  325. throw new \Exception('未指定更新的表名', __LINE__);
  326. }
  327. $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
  328. $this->whereCondition = array();
  329. $alias = $this->getTableAlias($table);
  330. $this->executeSQL = $this->modelSQL = $sql = sprintf($this->_query['DELETE'], $alias['name'], $where);
  331. return $this->exec($sql);
  332. }
  333. /**
  334. * 删除表中数据
  335. *
  336. * @param string $table 表名
  337. * @param null $where
  338. * @return string
  339. * @throws \Exception
  340. */
  341. final function deleteObject($table, $where = null)
  342. {
  343. if(!$table) {
  344. throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
  345. }
  346. return $this->where($where)->delete($table);
  347. }
  348. /**
  349. * like语句
  350. * @param mix $arr
  351. * @return $this
  352. */
  353. final function like($arr)
  354. {
  355. if(!is_array($arr)) {
  356. if(!empty($arr)) {
  357. $this->where($arr);
  358. }
  359. return $this;
  360. }
  361. foreach($arr as $key => $val) {
  362. $arr[$key .":like"] = $val;
  363. unset($arr[$key]);
  364. }
  365. $this->where($arr);
  366. return $this;
  367. }
  368. /**
  369. *
  370. * Limit函数,如果省略第二个参数则第一个为0,第二个参数值取第一个
  371. * @param int $limit
  372. * @param int $offset
  373. */
  374. final function limit($limit, $offset = null)
  375. {
  376. $this->limit = null;
  377. if($limit === '' || $limit === null) {
  378. throw new InvalidParams(_i('%s is invalid', 'Limit'), __LINE__);
  379. }
  380. if ($limit !== '') {
  381. if ($offset === null) {
  382. $this->limit = sprintf($this->_query["LIMIT"], 0, $limit);
  383. } else {
  384. $this->limit = sprintf($this->_query["LIMIT"], $limit, $offset);
  385. }
  386. }
  387. return $this;
  388. }
  389. /**
  390. * sql中的set条件
  391. *
  392. * @param array $set
  393. * @param null $res
  394. * @param string $defaultOperator
  395. * @return $this
  396. */
  397. final public function set($set, &$res = null, $defaultOperator = 'equal')
  398. {
  399. if(!is_array($set))
  400. {
  401. if(!empty($set))
  402. {
  403. $this->sets[] = $set;
  404. }
  405. return $this;
  406. }
  407. if(count($set) == 0) {
  408. return $this;
  409. }
  410. $operator = array("equal" => "%s`%s` = '%s'", "unequal" => "%s`%s` != '%s'", "plus" => "%s`%s` = %s`%s`+%s", "minus" => "%s`%s` = %s`%s`-%s", "multiply" => "%s`%s` = %s`%s`*%s", "divide" => "%s`%s` = %s`%s`/%s");
  411. foreach($set as $key => $val)
  412. {
  413. if(strtoupper(gettype($val)) != 'NULL') {
  414. $val = $this->setQuote($val);
  415. }
  416. $alias = $this->getFieldAlias($key);
  417. $operate = $this->getFieldOperator($alias['name']);
  418. if($operate['operator'] == '') {
  419. $operate['operator'] = $defaultOperator;
  420. }
  421. $opt = $operator[$operate['operator']];
  422. if(strtoupper(gettype($val)) == 'NULL') {
  423. $val = 'NULL';
  424. $opt = str_replace("'", '', $opt);
  425. }
  426. if($operate['operator'] == 'equal') {
  427. $this->sets[] = sprintf($opt, $alias['alias'], $operate['field'], $val);
  428. }else{
  429. $this->sets[] = sprintf($opt, $alias['alias'], $operate['field'], $alias['alias'], $operate['field'], $val);
  430. }
  431. }
  432. return $this;
  433. }
  434. /**
  435. * set 字段加
  436. * @param $set
  437. * @return $this
  438. */
  439. public function upsetCounter($set)
  440. {
  441. if(!is_array($set))
  442. {
  443. if(!empty($set))
  444. {
  445. $this->sets[] = $set;
  446. }
  447. return $this;
  448. }
  449. if(count($set) == 0) {
  450. return $this;
  451. }
  452. foreach ($set as $key => $val) {
  453. if(substr($key, -5) == ':plus') {
  454. continue;
  455. }
  456. $set[$key . ":plus"] = $val;
  457. unset($set[$key]);
  458. }
  459. return $this->set($set);
  460. }
  461. /**
  462. * set 字段减
  463. * @param $set
  464. * @return $this
  465. */
  466. public function downsetCounter($set)
  467. {
  468. if(!is_array($set)) {
  469. if(!empty($set)) {
  470. $this->sets[] = $set;
  471. }
  472. return $this;
  473. }
  474. if(count($set) == 0) {
  475. return $this;
  476. }
  477. foreach ($set as $key => $val) {
  478. if(substr($key, -6) == ':minus') {
  479. continue;
  480. }
  481. $set[$key . ":minus"] = $val;
  482. unset($set[$key]);
  483. }
  484. return $this->set($set);
  485. }
  486. /**
  487. * 处理where条件
  488. *
  489. * @param $where
  490. * @return $this|array
  491. * @throws \Exception
  492. */
  493. public function handleWhereFields($where) {
  494. if(!is_array($where)) {
  495. return $this;
  496. }
  497. $fields = [];
  498. foreach ($where as $key => $val) {
  499. $arr = explode(':', $key);
  500. $len = count($arr);
  501. $maxLen = 1;
  502. $opt = '';
  503. if(!$this->isExpression($arr[$len - 1])) {
  504. $maxLen = 0;
  505. }else{
  506. $opt = ':' .$arr[$len - 1];
  507. }
  508. if($len > $maxLen) {
  509. $arr1 = array_slice($arr, 0, count($arr) - $maxLen);
  510. foreach ($arr1 as $key) {
  511. $fields[$key . $opt] = $val;
  512. }
  513. }
  514. }
  515. return $fields;
  516. }
  517. /**
  518. * where条件
  519. * @param array $where where语句
  520. * @param null $res
  521. * @return $this
  522. */
  523. public function where($where, &$res = null)
  524. {
  525. if(!is_array($where)) {
  526. if(!empty($where))
  527. {
  528. if(!empty($this->whereCondition) && !$this->isOperator($where)) {
  529. $this->whereCondition[] = "and";
  530. }
  531. if($this->isOperator($where)) {
  532. $this->whereCondition[] = $where;
  533. }else{
  534. $this->whereCondition[] = "(". $where . ")";
  535. }
  536. }
  537. return $this;
  538. }
  539. if(count($where) == 0) {
  540. return $this;
  541. }
  542. $where = $this->handleWhereFields($where);
  543. $slices = $this->groupContents($where);
  544. $this->handleCondition($slices, $res);
  545. return $this;
  546. }
  547. /**
  548. * OR 条件
  549. * 用法:
  550. * 1:
  551. * $this->orTerms(['field1:like|equal....' => val1])->orTerms(....)
  552. * $this->orTerms(['field1:field2...:like|equal....' => val1])
  553. * == (field1 like|equal.... val1) or (field2 like|equal.... val1) ....
  554. * 2:
  555. * $this->orTerm(['field1:like|equal...' => val1, 'field2:like|equal...' => val1])
  556. * == (field1 like|equal.... val1 AND field2 like|equal.... val1 ....)
  557. * @param $where
  558. * @param string $defaultOperater
  559. * @param null $res
  560. * @return $this
  561. * @throws \Exception
  562. */
  563. public function orTerms($where, $defaultOperater = 'or', &$res = null)
  564. {
  565. if(!is_array($where))
  566. {
  567. if($where != '') {
  568. if(!empty($this->whereCondition) && !$this->isOperator($where)) {
  569. $this->whereCondition[] = $defaultOperater;
  570. }
  571. $this->whereCondition[] = "(". $where . ")";
  572. }
  573. return $this;
  574. }
  575. if(count($where) == 0) {
  576. return $this;
  577. }
  578. $extra = [];
  579. foreach ($where as $key => $val) {
  580. $fields = explode(':', $key);
  581. $len = count($fields);
  582. $min = 2;
  583. $opt = '';
  584. if($this->isExpression($fields[$len - 1])) {
  585. $min = 3;
  586. $opt = ':'. $fields[$len - 1];
  587. }
  588. if($len >= $min) {
  589. $arr = array_slice($fields, 0, ($opt != '' ? $len - 1 : $len));
  590. foreach ($arr as $field) {
  591. $extra[$field . $opt] = $val;
  592. }
  593. unset($where[$key]);
  594. }
  595. }
  596. if(count($where) > 0) {
  597. $this->handleCondition(array(array($defaultOperater, $where)), $res);
  598. }
  599. if(count($extra) > 0) {
  600. foreach ($extra as $key => $val) {
  601. $this->handleCondition(array(array($defaultOperater, [$key => $val])), $res);
  602. }
  603. }
  604. return $this;
  605. }
  606. /**
  607. * in 条件
  608. * @param $where
  609. * @param $defaultOperater
  610. * @param $res
  611. * @return $this
  612. * @throws \Exception
  613. */
  614. public function in($where, $defaultOperater = 'or', &$res = null)
  615. {
  616. if(!is_array($where))
  617. {
  618. if($where != '') {
  619. if(!empty($this->whereCondition) && !$this->isOperator($where)) {
  620. $this->whereCondition[] = $defaultOperater;
  621. }
  622. $this->whereCondition[] = "(". $where . ")";
  623. }
  624. return $this;
  625. }
  626. if(count($where) == 0) {
  627. return $this;
  628. }
  629. foreach ($where as $key => $val) {
  630. if(substr($key, - 3) == ':in') {
  631. continue;
  632. }
  633. $where[$key . ":in"] = $val;
  634. unset($where[$key]);
  635. }
  636. $where = $this->handleWhereFields($where);
  637. $this->handleCondition(array(array('and', $where)), $res);
  638. return $this;
  639. }
  640. /**
  641. * 不包含
  642. *
  643. * @param mix $where 条件
  644. * @return $this
  645. */
  646. public function exclude($where)
  647. {
  648. if(!is_array($where))
  649. {
  650. return $this->where($where);
  651. }
  652. if(count($where) == 0) {
  653. return $this;
  654. }
  655. foreach($where as $key => $value) {
  656. if($this->getFieldOperator($key)['operator'] == '') {
  657. $where[$key . ":unequal"] = $value;
  658. unset($where[$key]);
  659. }
  660. }
  661. return $this->where($where);
  662. }
  663. /**
  664. * join语句
  665. *
  666. * @param mix $val
  667. * @param reference $res 用于返回值
  668. * @return $this
  669. * @throws \Exception
  670. */
  671. public function join($val, &$res = null, $joinType = 'leftJoin') {
  672. if(!is_array($val)) {
  673. if(!empty($val)) {
  674. $this->joinCondition[] = $val;
  675. }
  676. return $this;
  677. }
  678. if(count($val) == 0) {
  679. return $this;
  680. }
  681. $slices = $this->groupContents($val);
  682. $this->handleTableJoin($slices, $joinType, $res);
  683. return $this;
  684. }
  685. /**
  686. * left join
  687. * @param $table
  688. * @param $on
  689. * @return $this
  690. * @throws \Exception
  691. */
  692. final function leftJoinObject($table, $on)
  693. {
  694. $alias = $this->getTableAlias($table);
  695. return $this->join(" LEFT JOIN ". $this->getTable($alias['name']) . " " . $alias['alias'] ." ON ". $on);
  696. }
  697. /**
  698. * GROUP BY
  699. * @param mix $group
  700. * @return $this
  701. */
  702. public function groupBy($group)
  703. {
  704. if(!is_array($group))
  705. {
  706. if(!empty($group))
  707. {
  708. $this->groupBy = stristr($group, 'GROUP BY') === false? "GROUP BY ". $group: $group;
  709. }
  710. return $this;
  711. }
  712. if(count($group) == 0) {
  713. return $this;
  714. }
  715. foreach($group as $index => $val)
  716. {
  717. $alias = $this->getFieldAlias($val);
  718. $group[$index] = $alias['alias'] . "`". $alias['name'] ."`";
  719. }
  720. $this->groupBy = " GROUP BY ". join(",", $group);
  721. return $this;
  722. }
  723. /**
  724. * Order by
  725. *
  726. * @param array|string $order
  727. * @return $this
  728. * @throws \Exception
  729. */
  730. public function orderBy($order)
  731. {
  732. if(!is_array($order))
  733. {
  734. if(!empty($order)) {
  735. $this->orderBy = stristr($order, 'ORDER BY') === false ? "ORDER BY ". $order: $order;
  736. }
  737. return $this;
  738. }
  739. if(count($order) == 0) {
  740. return $this;
  741. }
  742. $allowSortOff = array('asc', 'desc');
  743. $orderBy = array();
  744. $i = 0;
  745. $countOrder = count($order);
  746. foreach($order as $key => $sort)
  747. {
  748. if(!in_array(strtolower($sort), $allowSortOff) && $countOrder == $i)
  749. {
  750. throw new InvalidParams(_i('%s is invalid', 'sort'), __LINE__);
  751. }
  752. $alias = $this->getFieldAlias($key);
  753. $orderBy[] = $alias['alias'] . "`". $alias['name'] ."` ". $sort;
  754. $i++;
  755. }
  756. $this->orderBy = " ORDER BY ". join(",", $orderBy);
  757. return $this;
  758. }
  759. /**
  760. * Order by sql
  761. *
  762. * @param string $orderBy
  763. * @return $this
  764. * @throws \Exception
  765. */
  766. public function orderByStr($orderBy)
  767. {
  768. return $this->orderBy($orderBy);
  769. }
  770. /**
  771. * 过滤值
  772. *
  773. * @param string|array $word
  774. * @return array|string
  775. */
  776. final function setQuote($word)
  777. {
  778. if (ini_get("magic_quotes_gpc")) {
  779. return $word;
  780. }
  781. if(in_array(gettype($word), array("object", "resource","resource (closed)"))) {
  782. throw new \Exception('期待参数为数组或字符串,获取到的是:'. gettype($word)."(". json_encode($word) .")");
  783. }
  784. return is_array($word) ? array_map('addslashes', $word) : addslashes($word);
  785. }
  786. /**
  787. *
  788. * 查询的字段
  789. * @param string|array $fields
  790. * @return $this
  791. */
  792. final function fields($fields = "*", $append = false)
  793. {
  794. if (empty($fields) && !$append) $fields = "*";
  795. if (is_array($fields)) {
  796. if(count($fields) == 0) {
  797. $fields = $append ? '' : '*';
  798. }else{
  799. foreach($fields as $key => $val)
  800. {
  801. $alias = explode('.', $val);
  802. if(count($alias) > 1)
  803. {
  804. if(strpos("*", $alias[1]) !== false) {
  805. $fields[$key] = $val;
  806. continue;
  807. }
  808. $fields[$key] = $alias[0] . ".`".join(".", array_slice($alias, 1))."`";
  809. }
  810. }
  811. $fields = join(',', $fields);
  812. }
  813. }
  814. if($append) {
  815. if($fields != "") $this->fields .= ','. $fields;
  816. }else{
  817. $this->fields = $fields;
  818. }
  819. return $this;
  820. }
  821. /**
  822. * 清空Data数据
  823. */
  824. final public function cleanCondition()
  825. {
  826. $this->fields = '*';
  827. $this->whereCondition = array();
  828. $this->joinCondition = array();
  829. $this->groupBy = "";
  830. $this->orderBy = "";
  831. $this->limit = null;
  832. $this->sets = array();
  833. }
  834. /**
  835. * 获取错误码
  836. */
  837. final public function getCode()
  838. {
  839. return $this->response->getCode();
  840. }
  841. /**
  842. * 获取错误信息
  843. */
  844. final public function getMessage()
  845. {
  846. if ($this->response->isError()) {
  847. return $this->response->getMessage();
  848. }
  849. }
  850. /**
  851. * 返回response对象
  852. *
  853. * @return Response
  854. */
  855. public function getResponse()
  856. {
  857. return $this->response;
  858. }
  859. /**
  860. * 转换字符创
  861. *
  862. * @param $str
  863. * @return array|string
  864. */
  865. final public function iconv($str)
  866. {
  867. if (is_array($str)) {
  868. return array_map(function ($n) {
  869. return toUtf8($n);
  870. }, $str);
  871. }
  872. return toUtf8($str);
  873. }
  874. /**
  875. * 执行Model过程中保存的相关信息
  876. *
  877. * @param string $option
  878. * @return mixed
  879. */
  880. final function querySQL($option = '')
  881. {
  882. $allow = array('_queryTimes', '_querySeconds', '_errorInfo', '_exeSQL');
  883. if (in_array($option, $allow)) {
  884. return $this->{$option};
  885. }
  886. return 0;
  887. }
  888. /**
  889. * 获取执行的sql
  890. *
  891. * @param string $sql
  892. * @return $this
  893. */
  894. public function fetchSql(&$sql) {
  895. $this->executeSQL = &$sql;
  896. return $this;
  897. }
  898. /**
  899. * 通过where\set\limit等方法自动生成SQL语句
  900. *
  901. * @param string $table 必填
  902. * @return string
  903. * @throws \Exception
  904. */
  905. public function createSelectSQL($table)
  906. {
  907. if(!$table) {
  908. throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
  909. }
  910. $aliases = $this->getTableAlias($table);
  911. $fields = (trim($this->fields) != '') ? $this->fields : "*";
  912. //$this->fields = '*';
  913. if(count($this->whereCondition) > 0 && $this->isOperator($this->whereCondition[0])) {
  914. array_shift($this->whereCondition);
  915. }
  916. $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
  917. //$this->whereCondition = array();
  918. $join = count($this->joinCondition) > 0 ? join("\n", $this->joinCondition) : "";
  919. //$this->joinCondition = array();
  920. $groupBy = " ". $this->groupBy;
  921. //$this->groupBy = "";
  922. $orderBy = " ". $this->orderBy;
  923. //$this->orderBy = "";
  924. $limit = $this->limit;
  925. //$this->limit = null;
  926. $sql = sprintf($this->_query['SELECT'], $fields, $aliases['name'], $aliases['alias']) . $join . $where . $groupBy . $orderBy . $limit;
  927. $this->cleanCondition();
  928. $this->executeSQL = $this->modelSQL = $sql;
  929. return $sql;
  930. }
  931. /**
  932. * 获取操作符
  933. *
  934. * @param string $field 字段
  935. * @return array
  936. */
  937. protected function getFieldOperator($field)
  938. {
  939. $operator = explode(":", $field);
  940. if(count($operator) == 1) {
  941. return array('operator' => '', 'field' => $field);
  942. }
  943. $operate = array_pop($operator);
  944. $field = join(":", $operator);
  945. return array('operator' => $operate, 'field' => $field);
  946. }
  947. /**
  948. * 获取字段别名
  949. *
  950. * @param string $name
  951. * @param string $connector
  952. * @return array
  953. */
  954. protected function getFieldAlias($name, $connector = ".")
  955. {
  956. $aliases = explode('.', $name, 2);
  957. if(count($aliases) == 1) {
  958. return array('alias' => '', 'name' => $name);
  959. }
  960. return array('alias' => $aliases[0] . $connector, 'name' => join(".", array_slice($aliases, 1)));
  961. }
  962. /**
  963. * 获取表的别名
  964. *
  965. * @param string $name 名字
  966. * @return array
  967. */
  968. protected function getTableAlias($name)
  969. {
  970. if (!$this->verifyTable($name)) {
  971. if (gettype($name) == 'string') {
  972. throw new TableException("表名不能包含怪字符且不能以数字开头,获取到的是". $name);
  973. }
  974. throw new TableException("表名必须是字符串加下划线,目标字符为". gettype($name));
  975. }
  976. //去掉table前后的``符号
  977. $name = str_replace('`', '', $name);
  978. $aliases = explode(' ', $name);
  979. //检查表名中时候含数据库名,有数据表名的时候需要单独处理
  980. $hasDatabaseName = false;
  981. if(stristr($name, '.')) {
  982. $hasDatabaseName = true;
  983. }
  984. if(count($aliases) == 1) {
  985. if($hasDatabaseName) {
  986. $names = explode(".", $name);
  987. $name = $names[0] . ".`". $names[1] . "`";
  988. }else{
  989. $name = "`". $name ."`";
  990. }
  991. return array('alias' => '', 'name' => $name);
  992. }
  993. $res = array();
  994. $res['alias'] = array_pop($aliases);
  995. $res['name'] = join(" ", array_slice($aliases, -1));
  996. if($hasDatabaseName) {
  997. $names = explode(".", $res['name']);
  998. $res['name'] = $names[0] . ".`". $names[1] . "`";
  999. }else{
  1000. $res['name'] = "`". $res['name'] ."`";
  1001. }
  1002. return $res;
  1003. }
  1004. /**
  1005. * 把条件根据『链接字符串,『字段:值』』等内容分组
  1006. *
  1007. *
  1008. * $whereGroup = array(
  1009. * ['id' => 1, 'name' => '名字'],
  1010. * 'or',
  1011. * ['status' => 1, 'create_at:greater' => '22222'],//
  1012. * 'or',//链接字段与字段之间的操作符
  1013. * 'like',//使用在字段与值之间的操作符,可以省略
  1014. * 'and',//字段1与字段2之间的操作符
  1015. * 'or',//字段2与字段3之间的操作符
  1016. * '...',//字段n与字段n+1之间的操作符
  1017. * //字段n与字段n+1之间的操作符可以省略
  1018. * //子数组之间的操作符优先于上边的操作符
  1019. * ['email' => 'antsnet@163.com', "and", 'nickname' => 'antsnet'],
  1020. * ['uid' => 1],
  1021. * 'and',
  1022. * ['name' => 'ss'],
  1023. * 'and',
  1024. * 'and',
  1025. * 'update_at=1',
  1026. * );
  1027. * @param $group
  1028. * @return array [['or/and', 'like/equal/...', ['字段1' => '值1', '字段2' => '值2']],[...]]
  1029. * @throws \Exception
  1030. */
  1031. protected function groupContents($group)
  1032. {
  1033. $slices = array();
  1034. //如果是一维数组就直接操作值,不检查操作符
  1035. if(count($group) == count($group, 1)) {
  1036. $slices[] = array($group);
  1037. return $slices;
  1038. }
  1039. $count = count($group);
  1040. $tmpWhere = array();
  1041. //最后一次是否是赋值
  1042. $lastIsValue = null;
  1043. foreach($group as $index => $val)
  1044. {
  1045. //in比较特殊,它可以是字符串,可以是数组,结果是数组就单独处理不走操作符的处理逻辑
  1046. if(substr($index, -3) == ':in' && is_array($val)) {
  1047. $tmpWhere[$index] = $val;
  1048. continue;
  1049. }
  1050. if(is_array($val)) {
  1051. // group array 的情况,每组条件之间加 and
  1052. $slices[] = $this->groupContents($val)[0];
  1053. if($index < $count - 1) {
  1054. $slices[] = 'and';
  1055. }
  1056. continue;
  1057. }
  1058. $isOperator = $this->isOperator($val);//如果是操作符,上一个不是操作符就清空tmpWhere,并放入slices
  1059. $isValue = !$isOperator;
  1060. if($lastIsValue && $isOperator)
  1061. {
  1062. $slices[] = array_values($tmpWhere);
  1063. $tmpWhere = array();
  1064. $tmpWhere[$index] = $val;
  1065. }
  1066. else if($count - 1 == $index)
  1067. {
  1068. $tmpWhere[$index] = $val;
  1069. $slices[] = array_values($tmpWhere);
  1070. $tmpWhere = array();
  1071. }else {
  1072. $tmpWhere[$index] = $val;
  1073. }
  1074. $lastIsValue = $isValue;
  1075. }
  1076. // @todo 待测试
  1077. if(count($tmpWhere) > 0) {
  1078. //作为独立 slices 的条件
  1079. if(count($slices) > 0) {
  1080. $slices[] = "and";
  1081. }
  1082. $slices[][] = $tmpWhere;
  1083. }
  1084. return $slices;
  1085. }
  1086. /**
  1087. * 判断是否是操作符号
  1088. *
  1089. * @param mixed $val 值
  1090. * @return bool
  1091. */
  1092. protected function isOperator($val)
  1093. {
  1094. if(is_array($val)) {
  1095. return false;
  1096. }
  1097. if(!is_array($val)) {
  1098. if(in_array(gettype($val), array("array", "object", "resource","resource (closed)"))) {
  1099. throw new \Exception("期待参数为字符串,获取到的为: " . gettype($val) ."(". json_encode($val) . ")");
  1100. }
  1101. $val = strtolower($val);
  1102. }
  1103. return in_array($val, $this->operateVal) || in_array($val, $this->operateTable);
  1104. }
  1105. /**
  1106. * 判断是否是表达式 equal unequal ...
  1107. *
  1108. * @param string $val
  1109. * @return bool
  1110. * @throws \Exception
  1111. */
  1112. protected function isExpression($val) {
  1113. if(is_array($val)) {
  1114. return false;
  1115. }
  1116. if(in_array(gettype($val), array("array", "object", "resource","resource (closed)"))) {
  1117. throw new \Exception("期待参数为字符串,获取到的为: " . gettype($val) ."(". json_encode($val) . ")");
  1118. }
  1119. return isset($this->shortExpression[$val]);
  1120. }
  1121. /**
  1122. * 是否是操作表
  1123. *
  1124. * @param string $val 值
  1125. * @return bool
  1126. */
  1127. protected function isOperateTable($val)
  1128. {
  1129. if(is_array($val)) {
  1130. return false;
  1131. }
  1132. return in_array($val, $this->operateTable);
  1133. }
  1134. /**
  1135. * where条件子句组合
  1136. *
  1137. * @param array $values ['字段1' => '值1', '字段2' => '值2', ...]
  1138. * @param string $defaultOperate 默认字句的链接方式
  1139. * ..... 额外的参数,用于字段与字段之间的连接
  1140. * @return string
  1141. * @throws \Exception
  1142. */
  1143. protected function handleSubCondition($values, $defaultOperate = 'equal')
  1144. {
  1145. $extraParams = array();
  1146. if(func_num_args() > 2)
  1147. {
  1148. $extraParams = array_slice(func_get_args(), 2);
  1149. }
  1150. $where = array();
  1151. $operator = $this->shortExpression;
  1152. $lastIsOperator = false;
  1153. $lastIsValue = null;
  1154. $i = 0;
  1155. foreach($values as $key => $val)
  1156. {
  1157. $isOperator = preg_match("/^[0-9].*/", $key) && $this->isOperator($val);//如果是操作符,上一个不是操作符就清空tmpWhere,并放入slices
  1158. $isValue = !$isOperator;
  1159. if($lastIsValue && $isOperator)//如果当前是操作符,上一个是值,就将操作符加入到条件中
  1160. {
  1161. $where[] = $val;
  1162. $lastIsValue = $isValue;
  1163. $lastIsOperator = $isOperator;
  1164. continue;
  1165. }
  1166. //如果上一次是操作符,这次又是操作符,就是用当前的操作符,去掉上一个操作符
  1167. if($lastIsOperator && $isOperator)
  1168. {
  1169. if(!$this->faultTolerant) throw new InvalidParams(_i('Unsupported operator'), __LINE__);
  1170. array_pop($where);
  1171. $where[] = $val;
  1172. continue;
  1173. }
  1174. if($lastIsValue && $isValue)//需要添加操作符
  1175. {
  1176. $where[] = count($extraParams) > 0 && isset($extraParams[$i-1]) ? $extraParams[$i-1] : "and";
  1177. }
  1178. //$aliases = explode(".", $key);
  1179. $aliases = $this->getFieldAlias($key);
  1180. $alias = $aliases['alias'];
  1181. $operate = $this->getFieldOperator($aliases['name']);
  1182. $opt = $operate['operator'] ? $operate['operator'] : $defaultOperate;
  1183. $name = $operate['field'];
  1184. if($opt == 'in')
  1185. {
  1186. if(is_array($val)) {
  1187. $where[] = sprintf($operator[$opt], $alias, $name, "'". join("','", $val) . "'");
  1188. }else{
  1189. $where[] = sprintf($operator[$opt], $alias, $name, $val);
  1190. }
  1191. }else{
  1192. if(!isset($operator[$opt])) {
  1193. throw new \Exception("Unknow operator " . $opt, __LINE__);
  1194. }
  1195. $where[] = sprintf($operator[$opt], $alias, $name, $this->setQuote($val));
  1196. }
  1197. $lastIsValue = $isValue;
  1198. $lastIsOperator = $isOperator;
  1199. $i++;
  1200. }
  1201. return join(" ", $where);
  1202. }
  1203. /**
  1204. * 处理table join
  1205. * @param array $slices [['leftJoin', ['table' => '表名', 'alias' => 'a', 'on' => 'a.id = b.id']]]
  1206. * @param string $defaultJoin
  1207. * @param null $res
  1208. * @return $this
  1209. * @throws \Exception
  1210. */
  1211. protected function handleTableJoin($slices, $defaultJoin = 'leftJoin', &$res = null)
  1212. {
  1213. foreach ($slices as $v)
  1214. {
  1215. if(count($v) == 0) {
  1216. throw new \Exception('连接表操作失败,格式:"leftJoin/rightJoin/innerJoin", ["table" => "表名", "alias" => "b", "on" => "a.id=b.id"]', __LINE__);
  1217. }
  1218. if(count($v) == 1 && !$this->isOperateTable($v[0]))
  1219. {
  1220. array_unshift($v, $defaultJoin);
  1221. }
  1222. $joinOperator = array(
  1223. "leftJoin" => " LEFT JOIN %s ON %s",
  1224. "rightJoin" => " RIGHT JOIN %s ON %s",
  1225. "innerJoin" => " INNER JOIN %s ON %s"
  1226. );
  1227. if(!$this->isOperateTable($v[0]))
  1228. {
  1229. throw new \Exception('连接表操作失败,格式:"leftJoin/rightJoin/innerJoin", ["table" => "表名", "alias" => "b", "on" => "a.id=b.id"]', __LINE__);
  1230. }
  1231. $joinCondition = sprintf($joinOperator[$v[0]], $v[1]['table'] . ' '. $v[1]['alias'], $v[1]['on']);
  1232. if(!empty($this->join) && is_array($this->join))
  1233. {
  1234. $this->joinCondition = array_merge($this->join, array($joinCondition));
  1235. }
  1236. else
  1237. {
  1238. $this->joinCondition[] = $joinCondition;
  1239. }
  1240. $res[] = $joinCondition;
  1241. }
  1242. unset($joinCondition);
  1243. return $this;
  1244. }
  1245. /**
  1246. * 处理 where 条件
  1247. * @param array $condition
  1248. * @param null $res
  1249. * @return $this
  1250. * @throws \Exception
  1251. */
  1252. protected function handleCondition($condition, &$res = null)
  1253. {
  1254. if(!is_array($condition))
  1255. {
  1256. return $this;
  1257. }
  1258. $count = count($condition);
  1259. $whereCondition = array();
  1260. for($i = 0; $i < $count; $i++)
  1261. {
  1262. $v = $condition[$i];
  1263. if(!is_array($v) && $this->isOperator($v)) {
  1264. $whereCondition[] = ' and ';
  1265. continue;
  1266. }
  1267. //如果有两个及上的操作符
  1268. //默认第一个为连接其他条件的操作符,第二个位字段和值之间的操作符, 从第三个开始即为字段与字段之间的连接符
  1269. //最里层的字段与值之间的操作符优先级最高
  1270. //例如 1: 'or/and','like','or', 'and', ['uid' => 1, 'name' => '名字', 'status' => 激活];
  1271. //结果 1:or/and (uid like '%1%' or name like '%名字%' and status like '%激活%')
  1272. //例如 2: 'or/and','like','or', 'and', ['uid' => 1, 'name' => '名字', 'status:equal' => 激活];
  1273. //结果 2:or/and (uid like '%1%' or name like '%名字%' and status = '激活')
  1274. $operateCondition = array();
  1275. $values = array();
  1276. $countCondition = count($v);
  1277. $handleTable = false;
  1278. for($j = 0; $j < $countCondition; $j++)
  1279. {
  1280. $handleTable = false;
  1281. if($this->isOperateTable($v[$j]))
  1282. {
  1283. /*
  1284. $operateCondition[] = $v[$j];
  1285. $joinTable[$v[$j]] = $this->handleTableJoin($v);
  1286. */
  1287. //如果是操作数据表就直接退出循环单独处理
  1288. $handleTable = true;
  1289. break;
  1290. }
  1291. if($this->isOperator($v[$j]))
  1292. {
  1293. $operateCondition[] = $v[$j];
  1294. continue;
  1295. }
  1296. if(!$this->isOperator($v[$j]))
  1297. {
  1298. if(!is_array($v[$j])) {
  1299. $whereCondition[] = $v[0];
  1300. $whereCondition[] = "(". $v[1] . ")";
  1301. break;
  1302. }
  1303. $values = is_array($v[$j]) ? array_merge($values, $v[$j]) : array_merge($values, array($v[$j]));
  1304. }
  1305. }
  1306. if($handleTable)
  1307. {
  1308. continue;
  1309. }
  1310. if(count($operateCondition) > 0 && count($values) > 0)
  1311. {
  1312. $whereCondition[] = array_shift($operateCondition);
  1313. }
  1314. if(count($values) > 0) {
  1315. if(count($operateCondition) > 0) {
  1316. array_unshift($operateCondition, $values);
  1317. $whereCondition[] = "(". call_user_func_array(array($this, 'handleSubCondition'), $operateCondition) .")";
  1318. }else{
  1319. $whereCondition[] = "(". $this->handleSubCondition($values) .")";
  1320. }
  1321. }
  1322. }
  1323. if(!empty($this->whereCondition))
  1324. {
  1325. $lastCondition = $this->whereCondition[count($this->whereCondition) - 1];
  1326. if(count($whereCondition) > 0 && !$this->isOperator($whereCondition[0]) && !$this->isOperator($lastCondition)) {
  1327. $this->whereCondition = array_merge($this->whereCondition, array('and'));
  1328. }
  1329. $this->whereCondition = array_merge($this->whereCondition, $whereCondition);
  1330. }
  1331. else
  1332. {
  1333. $this->whereCondition = $whereCondition;
  1334. }
  1335. $res = $whereCondition;
  1336. unset($whereCondition);
  1337. return $this;
  1338. }
  1339. /**
  1340. * 验证数据表名是否符合规范
  1341. * 表名不能以数字开头,
  1342. *
  1343. * @param string $name
  1344. * @return bool
  1345. */
  1346. final public function verifyTable($name) {
  1347. if (!is_string($name) || (
  1348. // table
  1349. !preg_match("/^[a-zA-Z_]+[a-zA-Z0-9_]{0,}$/", $name) &&
  1350. // `table`
  1351. !preg_match("/^`[a-zA-Z_]+[a-zA-Z0-9_]{0,}`$/", $name)) &&
  1352. // table alias
  1353. !preg_match("/^[a-zA-Z_]+[a-zA-Z0-9_]{0,}\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
  1354. // `table` alias
  1355. !preg_match("/^`[a-zA-Z_]+[a-zA-Z0-9_]{0,}`\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
  1356. // database.table
  1357. !preg_match("/^[a-zA-Z]+\.[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
  1358. !preg_match("/^[a-zA-Z]+\.[a-zA-Z]+[a-zA-Z0-9_]{0,}\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name)
  1359. ) {
  1360. return false;
  1361. }
  1362. return true;
  1363. }
  1364. /**
  1365. * 如果不存在指定的方法则调用提示错误
  1366. *
  1367. * @param string $method
  1368. * @param mixd $args
  1369. * @return mixed
  1370. */
  1371. public function __call($method, $args)
  1372. {
  1373. if (isset($this->_modelAlias[$method])) {
  1374. if (method_exists($this, $this->_modelAlias[$method])) {
  1375. return call_user_func_array(array($this, $this->_modelAlias[$method]), $args);
  1376. }
  1377. return \Qii::setError(false, __LINE__, 1506, 'Alias ' . get_called_class() . '->' . $method . '() not found');
  1378. }
  1379. return \Qii::setError(false, __LINE__, 1506, get_called_class() . '->' . $method . '() not found');
  1380. }
  1381. }