query.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. <?php namespace Laravel\Database;
  2. use Closure;
  3. use Laravel\Database;
  4. use Laravel\Paginator;
  5. use Laravel\Database\Query\Grammars\SQLServer;
  6. class Query {
  7. /**
  8. * The database connection.
  9. *
  10. * @var Connection
  11. */
  12. public $connection;
  13. /**
  14. * The query grammar instance.
  15. *
  16. * @var Query\Grammars\Grammar
  17. */
  18. public $grammar;
  19. /**
  20. * The SELECT clause.
  21. *
  22. * @var array
  23. */
  24. public $selects;
  25. /**
  26. * The aggregating column and function.
  27. *
  28. * @var array
  29. */
  30. public $aggregate;
  31. /**
  32. * Indicates if the query should return distinct results.
  33. *
  34. * @var bool
  35. */
  36. public $distinct = false;
  37. /**
  38. * The table name.
  39. *
  40. * @var string
  41. */
  42. public $from;
  43. /**
  44. * The table joins.
  45. *
  46. * @var array
  47. */
  48. public $joins;
  49. /**
  50. * The WHERE clauses.
  51. *
  52. * @var array
  53. */
  54. public $wheres;
  55. /**
  56. * The GROUP BY clauses.
  57. *
  58. * @var array
  59. */
  60. public $groupings;
  61. /**
  62. * The HAVING clauses.
  63. *
  64. * @var array
  65. */
  66. public $havings;
  67. /**
  68. * The ORDER BY clauses.
  69. *
  70. * @var array
  71. */
  72. public $orderings;
  73. /**
  74. * The LIMIT value.
  75. *
  76. * @var int
  77. */
  78. public $limit;
  79. /**
  80. * The OFFSET value.
  81. *
  82. * @var int
  83. */
  84. public $offset;
  85. /**
  86. * The query value bindings.
  87. *
  88. * @var array
  89. */
  90. public $bindings = array();
  91. /**
  92. * Create a new query instance.
  93. *
  94. * @param Connection $connection
  95. * @param Grammar $grammar
  96. * @param string $table
  97. * @return void
  98. */
  99. public function __construct(Connection $connection, Query\Grammars\Grammar $grammar, $table)
  100. {
  101. $this->from = $table;
  102. $this->grammar = $grammar;
  103. $this->connection = $connection;
  104. }
  105. /**
  106. * Force the query to return distinct results.
  107. *
  108. * @return Query
  109. */
  110. public function distinct()
  111. {
  112. $this->distinct = true;
  113. return $this;
  114. }
  115. /**
  116. * Add an array of columns to the SELECT clause.
  117. *
  118. * @param array $columns
  119. * @return Query
  120. */
  121. public function select($columns = array('*'))
  122. {
  123. $this->selects = (array) $columns;
  124. return $this;
  125. }
  126. /**
  127. * Add a join clause to the query.
  128. *
  129. * @param string $table
  130. * @param string $column1
  131. * @param string $operator
  132. * @param string $column2
  133. * @param string $type
  134. * @return Query
  135. */
  136. public function join($table, $column1, $operator = null, $column2 = null, $type = 'INNER')
  137. {
  138. // If the "column" is really an instance of a Closure, the developer is
  139. // trying to create a join with a complex "ON" clause. So, we will add
  140. // the join, and then call the Closure with the join/
  141. if ($column1 instanceof Closure)
  142. {
  143. $this->joins[] = new Query\Join($type, $table);
  144. call_user_func($column1, end($this->joins));
  145. }
  146. // If the column is just a string, we can assume that the join just
  147. // has a simple on clause, and we'll create the join instance and
  148. // add the clause automatically for the develoepr.
  149. else
  150. {
  151. $join = new Query\Join($type, $table);
  152. $join->on($column1, $operator, $column2);
  153. $this->joins[] = $join;
  154. }
  155. return $this;
  156. }
  157. /**
  158. * Add a left join to the query.
  159. *
  160. * @param string $table
  161. * @param string $column1
  162. * @param string $operator
  163. * @param string $column2
  164. * @return Query
  165. */
  166. public function left_join($table, $column1, $operator = null, $column2 = null)
  167. {
  168. return $this->join($table, $column1, $operator, $column2, 'LEFT');
  169. }
  170. /**
  171. * Reset the where clause to its initial state.
  172. *
  173. * @return void
  174. */
  175. public function reset_where()
  176. {
  177. list($this->wheres, $this->bindings) = array(array(), array());
  178. }
  179. /**
  180. * Add a raw where condition to the query.
  181. *
  182. * @param string $where
  183. * @param array $bindings
  184. * @param string $connector
  185. * @return Query
  186. */
  187. public function raw_where($where, $bindings = array(), $connector = 'AND')
  188. {
  189. $this->wheres[] = array('type' => 'where_raw', 'connector' => $connector, 'sql' => $where);
  190. $this->bindings = array_merge($this->bindings, $bindings);
  191. return $this;
  192. }
  193. /**
  194. * Add a raw or where condition to the query.
  195. *
  196. * @param string $where
  197. * @param array $bindings
  198. * @return Query
  199. */
  200. public function raw_or_where($where, $bindings = array())
  201. {
  202. return $this->raw_where($where, $bindings, 'OR');
  203. }
  204. /**
  205. * Add a where condition to the query.
  206. *
  207. * @param string $column
  208. * @param string $operator
  209. * @param mixed $value
  210. * @param string $connector
  211. * @return Query
  212. */
  213. public function where($column, $operator = null, $value = null, $connector = 'AND')
  214. {
  215. // If a Closure is passed into the method, it means a nested where
  216. // clause is being initiated, so we will take a different course
  217. // of action than when the statement is just a simple where.
  218. if ($column instanceof Closure)
  219. {
  220. return $this->where_nested($column, $connector);
  221. }
  222. $type = 'where';
  223. $this->wheres[] = compact('type', 'column', 'operator', 'value', 'connector');
  224. $this->bindings[] = $value;
  225. return $this;
  226. }
  227. /**
  228. * Add an or where condition to the query.
  229. *
  230. * @param string $column
  231. * @param string $operator
  232. * @param mixed $value
  233. * @return Query
  234. */
  235. public function or_where($column, $operator = null, $value = null)
  236. {
  237. return $this->where($column, $operator, $value, 'OR');
  238. }
  239. /**
  240. * Add an or where condition for the primary key to the query.
  241. *
  242. * @param mixed $value
  243. * @return Query
  244. */
  245. public function or_where_id($value)
  246. {
  247. return $this->or_where('id', '=', $value);
  248. }
  249. /**
  250. * Add a where in condition to the query.
  251. *
  252. * @param string $column
  253. * @param array $values
  254. * @param string $connector
  255. * @param bool $not
  256. * @return Query
  257. */
  258. public function where_in($column, $values, $connector = 'AND', $not = false)
  259. {
  260. $type = ($not) ? 'where_not_in' : 'where_in';
  261. $this->wheres[] = compact('type', 'column', 'values', 'connector');
  262. $this->bindings = array_merge($this->bindings, $values);
  263. return $this;
  264. }
  265. /**
  266. * Add an or where in condition to the query.
  267. *
  268. * @param string $column
  269. * @param array $values
  270. * @return Query
  271. */
  272. public function or_where_in($column, $values)
  273. {
  274. return $this->where_in($column, $values, 'OR');
  275. }
  276. /**
  277. * Add a where not in condition to the query.
  278. *
  279. * @param string $column
  280. * @param array $values
  281. * @param string $connector
  282. * @return Query
  283. */
  284. public function where_not_in($column, $values, $connector = 'AND')
  285. {
  286. return $this->where_in($column, $values, $connector, true);
  287. }
  288. /**
  289. * Add an or where not in condition to the query.
  290. *
  291. * @param string $column
  292. * @param array $values
  293. * @return Query
  294. */
  295. public function or_where_not_in($column, $values)
  296. {
  297. return $this->where_not_in($column, $values, 'OR');
  298. }
  299. /**
  300. * Add a where null condition to the query.
  301. *
  302. * @param string $column
  303. * @param string $connector
  304. * @param bool $not
  305. * @return Query
  306. */
  307. public function where_null($column, $connector = 'AND', $not = false)
  308. {
  309. $type = ($not) ? 'where_not_null' : 'where_null';
  310. $this->wheres[] = compact('type', 'column', 'connector');
  311. return $this;
  312. }
  313. /**
  314. * Add an or where null condition to the query.
  315. *
  316. * @param string $column
  317. * @return Query
  318. */
  319. public function or_where_null($column)
  320. {
  321. return $this->where_null($column, 'OR');
  322. }
  323. /**
  324. * Add a where not null condition to the query.
  325. *
  326. * @param string $column
  327. * @param string $connector
  328. * @return Query
  329. */
  330. public function where_not_null($column, $connector = 'AND')
  331. {
  332. return $this->where_null($column, $connector, true);
  333. }
  334. /**
  335. * Add an or where not null condition to the query.
  336. *
  337. * @param string $column
  338. * @return Query
  339. */
  340. public function or_where_not_null($column)
  341. {
  342. return $this->where_not_null($column, 'OR');
  343. }
  344. /**
  345. * Add a nested where condition to the query.
  346. *
  347. * @param Closure $callback
  348. * @param string $connector
  349. * @return Query
  350. */
  351. public function where_nested($callback, $connector = 'AND')
  352. {
  353. $type = 'where_nested';
  354. // To handle a nested where statement, we will actually instantiate a new
  355. // Query instance and run the callback over that instance, which will
  356. // allow the developer to have a fresh query instance
  357. $query = new Query($this->connection, $this->grammar, $this->from);
  358. call_user_func($callback, $query);
  359. // Once the callback has been run on the query, we will store the nested
  360. // query instance on the where clause array so that it's passed to the
  361. // query's query grammar instance when building.
  362. if ($query->wheres !== null)
  363. {
  364. $this->wheres[] = compact('type', 'query', 'connector');
  365. }
  366. $this->bindings = array_merge($this->bindings, $query->bindings);
  367. return $this;
  368. }
  369. /**
  370. * Add dynamic where conditions to the query.
  371. *
  372. * @param string $method
  373. * @param array $parameters
  374. * @return Query
  375. */
  376. private function dynamic_where($method, $parameters)
  377. {
  378. $finder = substr($method, 6);
  379. $flags = PREG_SPLIT_DELIM_CAPTURE;
  380. $segments = preg_split('/(_and_|_or_)/i', $finder, -1, $flags);
  381. // The connector variable will determine which connector will be used
  382. // for the condition. We'll change it as we come across new boolean
  383. // connectors in the dynamic method string.
  384. //
  385. // The index variable helps us get the correct parameter value for
  386. // the where condition. We increment it each time we add another
  387. // condition to the query's where clause.
  388. $connector = 'AND';
  389. $index = 0;
  390. foreach ($segments as $segment)
  391. {
  392. // If the segment is not a boolean connector, we can assume it it is
  393. // a column name, and we'll add it to the query as a new constraint
  394. // of the query's where clause and keep iterating the segments.
  395. if ($segment != '_and_' and $segment != '_or_')
  396. {
  397. $this->where($segment, '=', $parameters[$index], $connector);
  398. $index++;
  399. }
  400. // Otherwise, we will store the connector so we know how the next
  401. // where clause we find in the query should be connected to the
  402. // previous one and will add it when we find the next one.
  403. else
  404. {
  405. $connector = trim(strtoupper($segment), '_');
  406. }
  407. }
  408. return $this;
  409. }
  410. /**
  411. * Add a grouping to the query.
  412. *
  413. * @param string $column
  414. * @return Query
  415. */
  416. public function group_by($column)
  417. {
  418. $this->groupings[] = $column;
  419. return $this;
  420. }
  421. /**
  422. * Add a having to the query.
  423. *
  424. * @param string $column
  425. * @param string $operator
  426. * @param mixed $value
  427. */
  428. public function having($column, $operator, $value)
  429. {
  430. $this->havings[] = compact('column', 'operator', 'value');
  431. $this->bindings[] = $value;
  432. return $this;
  433. }
  434. /**
  435. * Add an ordering to the query.
  436. *
  437. * @param string $column
  438. * @param string $direction
  439. * @return Query
  440. */
  441. public function order_by($column, $direction = 'asc')
  442. {
  443. $this->orderings[] = compact('column', 'direction');
  444. return $this;
  445. }
  446. /**
  447. * Set the query offset.
  448. *
  449. * @param int $value
  450. * @return Query
  451. */
  452. public function skip($value)
  453. {
  454. $this->offset = $value;
  455. return $this;
  456. }
  457. /**
  458. * Set the query limit.
  459. *
  460. * @param int $value
  461. * @return Query
  462. */
  463. public function take($value)
  464. {
  465. $this->limit = $value;
  466. return $this;
  467. }
  468. /**
  469. * Set the query limit and offset for a given page.
  470. *
  471. * @param int $page
  472. * @param int $per_page
  473. * @return Query
  474. */
  475. public function for_page($page, $per_page)
  476. {
  477. return $this->skip(($page - 1) * $per_page)->take($per_page);
  478. }
  479. /**
  480. * Find a record by the primary key.
  481. *
  482. * @param int $id
  483. * @param array $columns
  484. * @return object
  485. */
  486. public function find($id, $columns = array('*'))
  487. {
  488. return $this->where('id', '=', $id)->first($columns);
  489. }
  490. /**
  491. * Execute the query as a SELECT statement and return a single column.
  492. *
  493. * @param string $column
  494. * @return mixed
  495. */
  496. public function only($column)
  497. {
  498. $sql = $this->grammar->select($this->select(array($column)));
  499. return $this->connection->only($sql, $this->bindings);
  500. }
  501. /**
  502. * Execute the query as a SELECT statement and return the first result.
  503. *
  504. * @param array $columns
  505. * @return mixed
  506. */
  507. public function first($columns = array('*'))
  508. {
  509. $columns = (array) $columns;
  510. // Since we only need the first result, we'll go ahead and set the
  511. // limit clause to 1, since this will be much faster than getting
  512. // all of the rows and then only returning the first.
  513. $results = $this->take(1)->get($columns);
  514. return (count($results) > 0) ? $results[0] : null;
  515. }
  516. /**
  517. * Get an array with the values of a given column.
  518. *
  519. * @param string $column
  520. * @param string $key
  521. * @return array
  522. */
  523. public function lists($column, $key = null)
  524. {
  525. $columns = (is_null($key)) ? array($column) : array($column, $key);
  526. $results = $this->get($columns);
  527. // First we will get the array of values for the requested column.
  528. // Of course, this array will simply have numeric keys. After we
  529. // have this array we will determine if we need to key the array
  530. // by another column from the result set.
  531. $values = array_map(function($row) use ($column)
  532. {
  533. return $row->$column;
  534. }, $results);
  535. // If a key was provided, we will extract an array of keys and
  536. // set the keys on the array of values using the array_combine
  537. // function provided by PHP, which should give us the proper
  538. // array form to return from the method.
  539. if ( ! is_null($key))
  540. {
  541. return array_combine(array_map(function($row) use ($key)
  542. {
  543. return $row->$key;
  544. }, $results), $values);
  545. }
  546. return $values;
  547. }
  548. /**
  549. * Execute the query as a SELECT statement.
  550. *
  551. * @param array $columns
  552. * @return array
  553. */
  554. public function get($columns = array('*'))
  555. {
  556. if (is_null($this->selects)) $this->select($columns);
  557. $sql = $this->grammar->select($this);
  558. $results = $this->connection->query($sql, $this->bindings);
  559. // If the query has an offset and we are using the SQL Server grammar,
  560. // we need to spin through the results and remove the "rownum" from
  561. // each of the objects since there is no "offset".
  562. if ($this->offset > 0 and $this->grammar instanceof SQLServer)
  563. {
  564. array_walk($results, function($result)
  565. {
  566. unset($result->rownum);
  567. });
  568. }
  569. // Reset the SELECT clause so more queries can be performed using
  570. // the same instance. This is helpful for getting aggregates and
  571. // then getting actual results from the query.
  572. $this->selects = null;
  573. return $results;
  574. }
  575. /**
  576. * Get an aggregate value.
  577. *
  578. * @param string $aggregator
  579. * @param array $columns
  580. * @return mixed
  581. */
  582. public function aggregate($aggregator, $columns)
  583. {
  584. // We'll set the aggregate value so the grammar does not try to compile
  585. // a SELECT clause on the query. If an aggregator is present, it's own
  586. // grammar function will be used to build the SQL syntax.
  587. $this->aggregate = compact('aggregator', 'columns');
  588. $sql = $this->grammar->select($this);
  589. $result = $this->connection->only($sql, $this->bindings);
  590. // Reset the aggregate so more queries can be performed using the same
  591. // instance. This is helpful for getting aggregates and then getting
  592. // actual results from the query such as during paging.
  593. $this->aggregate = null;
  594. return $result;
  595. }
  596. /**
  597. * Get the paginated query results as a Paginator instance.
  598. *
  599. * @param int $per_page
  600. * @param array $columns
  601. * @return Paginator
  602. */
  603. public function paginate($per_page = 20, $columns = array('*'))
  604. {
  605. // Because some database engines may throw errors if we leave orderings
  606. // on the query when retrieving the total number of records, we'll drop
  607. // all of the ordreings and put them back on the query.
  608. list($orderings, $this->orderings) = array($this->orderings, null);
  609. $total = $this->count(reset($columns));
  610. $page = Paginator::page($total, $per_page);
  611. $this->orderings = $orderings;
  612. // Now we're ready to get the actual pagination results from the table
  613. // using the for_page and get methods. The "for_page" method provides
  614. // a convenient way to set the paging limit and offset.
  615. $results = $this->for_page($page, $per_page)->get($columns);
  616. return Paginator::make($results, $total, $per_page);
  617. }
  618. /**
  619. * Insert an array of values into the database table.
  620. *
  621. * @param array $values
  622. * @return bool
  623. */
  624. public function insert($values)
  625. {
  626. // Force every insert to be treated like a batch insert to make creating
  627. // the binding array simpler since we can just spin through the inserted
  628. // rows as if there/ was more than one every time.
  629. if ( ! is_array(reset($values))) $values = array($values);
  630. $bindings = array();
  631. // We need to merge the the insert values into the array of the query
  632. // bindings so that they will be bound to the PDO statement when it
  633. // is executed by the database connection.
  634. foreach ($values as $value)
  635. {
  636. $bindings = array_merge($bindings, array_values($value));
  637. }
  638. $sql = $this->grammar->insert($this, $values);
  639. return $this->connection->query($sql, $bindings);
  640. }
  641. /**
  642. * Insert an array of values into the database table and return the ID.
  643. *
  644. * @param array $values
  645. * @param string $sequence
  646. * @return int
  647. */
  648. public function insert_get_id($values, $sequence = null)
  649. {
  650. $sql = $this->grammar->insert($this, $values);
  651. $this->connection->query($sql, array_values($values));
  652. // Some database systems (Postgres) require a sequence name to be
  653. // given when retrieving the auto-incrementing ID, so we'll pass
  654. // the given sequence into the method just in case.
  655. return (int) $this->connection->pdo->lastInsertId($sequence);
  656. }
  657. /**
  658. * Increment the value of a column by a given amount.
  659. *
  660. * @param string $column
  661. * @param int $amount
  662. * @return int
  663. */
  664. public function increment($column, $amount = 1)
  665. {
  666. return $this->adjust($column, $amount, ' + ');
  667. }
  668. /**
  669. * Decrement the value of a column by a given amount.
  670. *
  671. * @param string $column
  672. * @param int $amount
  673. * @return int
  674. */
  675. public function decrement($column, $amount = 1)
  676. {
  677. return $this->adjust($column, $amount, ' - ');
  678. }
  679. /**
  680. * Adjust the value of a column up or down by a given amount.
  681. *
  682. * @param string $column
  683. * @param int $amount
  684. * @param string $operator
  685. * @return int
  686. */
  687. protected function adjust($column, $amount, $operator)
  688. {
  689. $wrapped = $this->grammar->wrap($column);
  690. // To make the adjustment to the column, we'll wrap the expression in an
  691. // Expression instance, which forces the adjustment to be injected into
  692. // the query as a string instead of bound.
  693. $value = Database::raw($wrapped.$operator.$amount);
  694. return $this->update(array($column => $value));
  695. }
  696. /**
  697. * Update an array of values in the database table.
  698. *
  699. * @param array $values
  700. * @return int
  701. */
  702. public function update($values)
  703. {
  704. // For update statements, we need to merge the bindings such that the update
  705. // values occur before the where bindings in the array since the sets will
  706. // precede any of the where clauses in the SQL syntax that is generated.
  707. $bindings = array_merge(array_values($values), $this->bindings);
  708. $sql = $this->grammar->update($this, $values);
  709. return $this->connection->query($sql, $bindings);
  710. }
  711. /**
  712. * Execute the query as a DELETE statement.
  713. *
  714. * Optionally, an ID may be passed to the method do delete a specific row.
  715. *
  716. * @param int $id
  717. * @return int
  718. */
  719. public function delete($id = null)
  720. {
  721. // If an ID is given to the method, we'll set the where clause to
  722. // match on the value of the ID. This allows the developer to
  723. // quickly delete a row by its primary key value.
  724. if ( ! is_null($id))
  725. {
  726. $this->where('id', '=', $id);
  727. }
  728. $sql = $this->grammar->delete($this);
  729. return $this->connection->query($sql, $this->bindings);
  730. }
  731. /**
  732. * Magic Method for handling dynamic functions.
  733. *
  734. * This method handles calls to aggregates as well as dynamic where clauses.
  735. */
  736. public function __call($method, $parameters)
  737. {
  738. if (strpos($method, 'where_') === 0)
  739. {
  740. return $this->dynamic_where($method, $parameters, $this);
  741. }
  742. // All of the aggregate methods are handled by a single method, so we'll
  743. // catch them all here and then pass them off to the agregate method
  744. // instead of creating methods for each one of them.
  745. if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
  746. {
  747. if (count($parameters) == 0) $parameters[0] = '*';
  748. return $this->aggregate(strtoupper($method), (array) $parameters[0]);
  749. }
  750. throw new \Exception("Method [$method] is not defined on the Query class.");
  751. }
  752. }