Query.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <?php
  2. namespace PhpLife\Frame\Library\MySQL;
  3. /**
  4. * 查询生成器
  5. */
  6. class Query
  7. {
  8. const PREPARE_PREFIX = ':prepared_';
  9. private $tableName;
  10. private $operation = 'SELECT';
  11. private $field = array();
  12. private $primaryKey = '';
  13. private $data = array();
  14. private $where;
  15. private $orderBy;
  16. private $groupBy;
  17. private $limit = 'LIMIT 2000';
  18. //替换后的映射表
  19. private $prepared = array();
  20. private $sql = '';
  21. /**
  22. * 实例
  23. * @return Query
  24. */
  25. public static function newInstance()
  26. {
  27. return new Query();
  28. }
  29. /**
  30. * 获取select
  31. * @return Query
  32. */
  33. public function select()
  34. {
  35. $this->operation = 'SELECT';
  36. return $this;
  37. }
  38. /**
  39. * 获取count
  40. * @return Query
  41. */
  42. public function count()
  43. {
  44. $this->operation = 'COUNT';
  45. return $this;
  46. }
  47. /**
  48. * 插入条记录
  49. * @return Query
  50. */
  51. public function insert()
  52. {
  53. $this->operation = 'INSERT';
  54. return $this;
  55. }
  56. /**
  57. * replace into
  58. * @return Query
  59. */
  60. public function replace()
  61. {
  62. $this->operation = 'REPLACE';
  63. return $this;
  64. }
  65. /**
  66. * 更新
  67. * @return Query
  68. */
  69. public function update()
  70. {
  71. $this->operation = 'UPDATE';
  72. return $this;
  73. }
  74. /**
  75. * 删除
  76. * @return Query
  77. */
  78. public function delete()
  79. {
  80. $this->operation = 'DELETE';
  81. return $this;
  82. }
  83. /**
  84. * 设置表名
  85. * @param string $tableName
  86. * @return Query
  87. */
  88. public function setTableName($tableName)
  89. {
  90. if ($tableName) {
  91. $this->tableName = $this->_prepareFieldName($tableName);
  92. }
  93. return $this;
  94. }
  95. /**
  96. * 设置字段
  97. * @param Array /String $field
  98. * @return Query
  99. */
  100. public function setField($field)
  101. {
  102. if ($field) {
  103. if (!is_array($field)) {
  104. $field = explode(',', $field);
  105. }
  106. $this->field = $field;
  107. }
  108. return $this;
  109. }
  110. /**
  111. * 设置主键名
  112. * @param $primaryKey
  113. * @return $this
  114. */
  115. public function setPrimaryKey($primaryKey)
  116. {
  117. if ($primaryKey) {
  118. $this->primaryKey = trim($primaryKey);
  119. }
  120. return $this;
  121. }
  122. /**
  123. * 设置where条件
  124. * @param array $where
  125. * @param string $whereString
  126. * @return Query
  127. */
  128. public function setWhere(Array $where, $whereString = '')
  129. {
  130. if (empty($where) && empty($whereString)) {
  131. return $this;
  132. }
  133. if ($whereString) {
  134. foreach ($where as $key => $val) {
  135. $preparedKeys = array();
  136. if (is_array($val)) {
  137. foreach ($val as $row) {
  138. $preparedKeys[] = $this->_prepareData($row);
  139. }
  140. } else {
  141. $preparedKeys[] = $this->_prepareData($val);
  142. }
  143. $key = ':' . ltrim($key, ':');
  144. $whereString = str_replace($key, implode(',', $preparedKeys), $whereString);
  145. }
  146. $this->where = 'WHERE ' . $whereString;
  147. } elseif ($where) {
  148. $data = array();
  149. foreach ($where as $key => $val) {
  150. if (is_array($val)) {
  151. $preparedKeys = array();
  152. foreach ($val as $row) {
  153. $preparedKeys[] = $this->_prepareData($row);
  154. }
  155. $data[] = $this->_prepareFieldName($key) . ' IN (' . implode(',', $preparedKeys) . ')';
  156. } else {
  157. $data[] = $this->_prepareFieldName($key) . " = " . $this->_prepareData($val);
  158. }
  159. }
  160. $this->where = 'WHERE ' . implode(' AND ', $data);
  161. }
  162. return $this;
  163. }
  164. /**
  165. * 设置排序
  166. * @param Array $orderBy = array('id' => 1); value 是 true 表示倒序,反之是正序
  167. * @return Query
  168. */
  169. public function setOrderBy(Array $orderBy)
  170. {
  171. if ($orderBy && is_array($orderBy)) {
  172. $tmp = array();
  173. foreach ($orderBy as $key => $val) {
  174. if (is_numeric($key)) {
  175. continue;
  176. }
  177. $order = $val ? 'DESC' : 'ASC';
  178. $tmp[] = $this->_prepareFieldName($key) . ' ' . $order;
  179. }
  180. $tmp = implode(',', $tmp);
  181. $this->orderBy = "ORDER BY " . $tmp;
  182. }
  183. return $this;
  184. }
  185. /**
  186. * 设置范围
  187. * @param int $limit
  188. * @param int $offset
  189. * @return Query
  190. */
  191. public function setLimit($limit = 2000, $offset = 0)
  192. {
  193. if ($limit) {
  194. $this->limit = 'LIMIT ' . intval($offset) . ',' . intval($limit);
  195. } else {
  196. $this->limit = '';
  197. }
  198. return $this;
  199. }
  200. /**
  201. * 设置分组
  202. * @param Array /String $groupBy
  203. * @return Query
  204. */
  205. public function setGroupBy($groupBy)
  206. {
  207. if (empty($groupBy)) {
  208. return $this;
  209. }
  210. if (is_array($groupBy)) {
  211. $tmp = array();
  212. foreach ($groupBy as $v) {
  213. $tmp[] = $this->_prepareFieldName($v);
  214. }
  215. $this->groupBy = 'GROUP BY ' . implode(",", $tmp);
  216. } else {
  217. $this->groupBy = 'GROUP BY ' . $this->_prepareFieldName($groupBy);
  218. }
  219. return $this;
  220. }
  221. /**
  222. * 设置数据
  223. * @param Array $data
  224. * @return Query
  225. */
  226. public function setData(Array $data)
  227. {
  228. if ($data) {
  229. $this->data = $data;
  230. }
  231. return $this;
  232. }
  233. /**
  234. * 获取相关SQL
  235. * @param boolean $raw
  236. * @return String $sql
  237. */
  238. public function getSQL($raw = false)
  239. {
  240. $sql = $this->_getSQL();
  241. if ($raw) {
  242. foreach ($this->prepared as $key => $value) {
  243. $key = ':' . trim($key, ':');
  244. if (is_array($value)) {
  245. foreach ($value as $k => $v) {
  246. $value[$k] = addslashes($v);
  247. }
  248. $value = implode(',', $value);
  249. } else {
  250. $value = "'" . addslashes($value) . "'";
  251. }
  252. $sql = str_replace($key, $value, $sql);
  253. }
  254. }
  255. return $sql;
  256. }
  257. /**
  258. * 返回Prepare过的数据
  259. * @return Array
  260. */
  261. public function getData()
  262. {
  263. $sql = $this->_getSQL();
  264. $data = array();
  265. foreach ($this->prepared as $key => $value) {
  266. if (strpos($sql, $key) !== false) {
  267. $key = ltrim($key, ':');
  268. $data[$key] = $value;
  269. }
  270. }
  271. return $data;
  272. }
  273. /**
  274. * 拼SQL
  275. * @return string
  276. */
  277. private function _getSQL()
  278. {
  279. if ($this->sql) {
  280. return $this->sql;
  281. }
  282. switch ($this->operation) {
  283. case 'INSERT':
  284. $sql = 'INSERT INTO ' . $this->tableName . ' SET ' . $this->_getData();
  285. break;
  286. case 'UPDATE':
  287. $sql = 'UPDATE ' . $this->tableName . ' SET ' . $this->_getData() . ' ' . $this->where;
  288. break;
  289. case 'REPLACE':
  290. $sql = 'REPLACE INTO ' . $this->tableName . ' SET ' . $this->_getData();
  291. break;
  292. case 'DELETE':
  293. $sql = 'DELETE FROM ' . $this->tableName . ' ' . $this->where;
  294. break;
  295. case 'COUNT':
  296. $sql = 'SELECT COUNT(*) AS `count` FROM ' . $this->tableName . ' ' . $this->where . ' ' . $this->groupBy;
  297. break;
  298. case 'SELECT':
  299. default:
  300. $sql = 'SELECT ' . $this->_getField() . ' FROM ' . $this->tableName . ' ' . $this->where . ' ' . $this->orderBy . ' ' . $this->groupBy . ' ' . $this->limit;
  301. break;
  302. }
  303. return $this->sql = $sql;
  304. }
  305. /**
  306. * 获取字段名称
  307. * @return String
  308. */
  309. private function _getField()
  310. {
  311. if (empty($this->field)) {
  312. $field = '*';
  313. } else {
  314. $tmp = array();
  315. foreach ($this->field as $v) {
  316. if(strstr($v,'sum')){
  317. $tmp[] = $v;
  318. }else{
  319. $tmp[] = $this->_prepareFieldName($v);
  320. }
  321. }
  322. $field = implode(",", $tmp);
  323. }
  324. return $field;
  325. }
  326. /**
  327. * 获取prepare后的数据
  328. * @return String
  329. */
  330. private function _getData()
  331. {
  332. $data = array();
  333. foreach ($this->data as $key => $value) {
  334. //简单字段检查
  335. if (($this->field AND !in_array($key, $this->field)) || is_null($value)) {
  336. continue;
  337. }
  338. $data[$key] = $this->_prepareFieldName($key) . ' = ' . $this->_prepareData($value);
  339. }
  340. $data = implode(",", $data);
  341. return $data;
  342. }
  343. /**
  344. * 过滤字段名,表名
  345. * @param String $value
  346. * @return string
  347. */
  348. private function _prepareFieldName($value)
  349. {
  350. $value = strtr($value, array(' ' => '', '`' => ''));
  351. $value = "`" . $value . "`";
  352. return $value;
  353. }
  354. /**
  355. * prepare替换
  356. * @param String $value
  357. * @return string
  358. */
  359. private function _prepareData($value)
  360. {
  361. $count = count($this->prepared);
  362. $key = self::PREPARE_PREFIX . $count . '_';
  363. $this->prepared[$key] = $value;
  364. return $key;
  365. }
  366. /**
  367. * 魔术输出方法
  368. * @return String
  369. */
  370. public function __toString()
  371. {
  372. return $this->getSQL();
  373. }
  374. }