query.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  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. $this->wheres[] = compact('type', 'query', 'connector');
  363. $this->bindings = array_merge($this->bindings, $query->bindings);
  364. return $this;
  365. }
  366. /**
  367. * Add dynamic where conditions to the query.
  368. *
  369. * @param string $method
  370. * @param array $parameters
  371. * @return Query
  372. */
  373. private function dynamic_where($method, $parameters)
  374. {
  375. $finder = substr($method, 6);
  376. $flags = PREG_SPLIT_DELIM_CAPTURE;
  377. $segments = preg_split('/(_and_|_or_)/i', $finder, -1, $flags);
  378. // The connector variable will determine which connector will be used
  379. // for the condition. We'll change it as we come across new boolean
  380. // connectors in the dynamic method string.
  381. //
  382. // The index variable helps us get the correct parameter value for
  383. // the where condition. We increment it each time we add another
  384. // condition to the query's where clause.
  385. $connector = 'AND';
  386. $index = 0;
  387. foreach ($segments as $segment)
  388. {
  389. // If the segment is not a boolean connector, we can assume it it is
  390. // a column name, and we'll add it to the query as a new constraint
  391. // of the query's where clause and keep iterating the segments.
  392. if ($segment != '_and_' and $segment != '_or_')
  393. {
  394. $this->where($segment, '=', $parameters[$index], $connector);
  395. $index++;
  396. }
  397. // Otherwise, we will store the connector so we know how the next
  398. // where clause we find in the query should be connected to the
  399. // previous one and will add it when we find the next one.
  400. else
  401. {
  402. $connector = trim(strtoupper($segment), '_');
  403. }
  404. }
  405. return $this;
  406. }
  407. /**
  408. * Add a grouping to the query.
  409. *
  410. * @param string $column
  411. * @return Query
  412. */
  413. public function group_by($column)
  414. {
  415. $this->groupings[] = $column;
  416. return $this;
  417. }
  418. /**
  419. * Add a having to the query.
  420. *
  421. * @param string $column
  422. * @param string $operator
  423. * @param mixed $value
  424. */
  425. public function having($column, $operator, $value)
  426. {
  427. $this->havings[] = compact('column', 'operator', 'value');
  428. $this->bindings[] = $value;
  429. return $this;
  430. }
  431. /**
  432. * Add an ordering to the query.
  433. *
  434. * @param string $column
  435. * @param string $direction
  436. * @return Query
  437. */
  438. public function order_by($column, $direction = 'asc')
  439. {
  440. $this->orderings[] = compact('column', 'direction');
  441. return $this;
  442. }
  443. /**
  444. * Set the query offset.
  445. *
  446. * @param int $value
  447. * @return Query
  448. */
  449. public function skip($value)
  450. {
  451. $this->offset = $value;
  452. return $this;
  453. }
  454. /**
  455. * Set the query limit.
  456. *
  457. * @param int $value
  458. * @return Query
  459. */
  460. public function take($value)
  461. {
  462. $this->limit = $value;
  463. return $this;
  464. }
  465. /**
  466. * Set the query limit and offset for a given page.
  467. *
  468. * @param int $page
  469. * @param int $per_page
  470. * @return Query
  471. */
  472. public function for_page($page, $per_page)
  473. {
  474. return $this->skip(($page - 1) * $per_page)->take($per_page);
  475. }
  476. /**
  477. * Find a record by the primary key.
  478. *
  479. * @param int $id
  480. * @param array $columns
  481. * @return object
  482. */
  483. public function find($id, $columns = array('*'))
  484. {
  485. return $this->where('id', '=', $id)->first($columns);
  486. }
  487. /**
  488. * Execute the query as a SELECT statement and return a single column.
  489. *
  490. * @param string $column
  491. * @return mixed
  492. */
  493. public function only($column)
  494. {
  495. $sql = $this->grammar->select($this->select(array($column)));
  496. return $this->connection->only($sql, $this->bindings);
  497. }
  498. /**
  499. * Execute the query as a SELECT statement and return the first result.
  500. *
  501. * @param array $columns
  502. * @return mixed
  503. */
  504. public function first($columns = array('*'))
  505. {
  506. $columns = (array) $columns;
  507. // Since we only need the first result, we'll go ahead and set the
  508. // limit clause to 1, since this will be much faster than getting
  509. // all of the rows and then only returning the first.
  510. $results = $this->take(1)->get($columns);
  511. return (count($results) > 0) ? $results[0] : null;
  512. }
  513. /**
  514. * Get an array with the values of a given column.
  515. *
  516. * @param string $column
  517. * @param string $key
  518. * @return array
  519. */
  520. public function lists($column, $key = null)
  521. {
  522. $columns = (is_null($key)) ? array($column) : array($column, $key);
  523. $results = $this->get($columns);
  524. // First we will get the array of values for the requested column.
  525. // Of course, this array will simply have numeric keys. After we
  526. // have this array we will determine if we need to key the array
  527. // by another column from the result set.
  528. $values = array_map(function($row) use ($column)
  529. {
  530. return $row->$column;
  531. }, $results);
  532. // If a key was provided, we will extract an array of keys and
  533. // set the keys on the array of values using the array_combine
  534. // function provided by PHP, which should give us the proper
  535. // array form to return from the method.
  536. if ( ! is_null($key))
  537. {
  538. return array_combine(array_map(function($row) use ($key)
  539. {
  540. return $row->$key;
  541. }, $results), $values);
  542. }
  543. return $values;
  544. }
  545. /**
  546. * Execute the query as a SELECT statement.
  547. *
  548. * @param array $columns
  549. * @return array
  550. */
  551. public function get($columns = array('*'))
  552. {
  553. if (is_null($this->selects)) $this->select($columns);
  554. $sql = $this->grammar->select($this);
  555. $results = $this->connection->query($sql, $this->bindings);
  556. // If the query has an offset and we are using the SQL Server grammar,
  557. // we need to spin through the results and remove the "rownum" from
  558. // each of the objects since there is no "offset".
  559. if ($this->offset > 0 and $this->grammar instanceof SQLServer)
  560. {
  561. array_walk($results, function($result)
  562. {
  563. unset($result->rownum);
  564. });
  565. }
  566. // Reset the SELECT clause so more queries can be performed using
  567. // the same instance. This is helpful for getting aggregates and
  568. // then getting actual results from the query.
  569. $this->selects = null;
  570. return $results;
  571. }
  572. /**
  573. * Get an aggregate value.
  574. *
  575. * @param string $aggregator
  576. * @param array $columns
  577. * @return mixed
  578. */
  579. public function aggregate($aggregator, $columns)
  580. {
  581. // We'll set the aggregate value so the grammar does not try to compile
  582. // a SELECT clause on the query. If an aggregator is present, it's own
  583. // grammar function will be used to build the SQL syntax.
  584. $this->aggregate = compact('aggregator', 'columns');
  585. $sql = $this->grammar->select($this);
  586. $result = $this->connection->only($sql, $this->bindings);
  587. // Reset the aggregate so more queries can be performed using the same
  588. // instance. This is helpful for getting aggregates and then getting
  589. // actual results from the query such as during paging.
  590. $this->aggregate = null;
  591. return $result;
  592. }
  593. /**
  594. * Get the paginated query results as a Paginator instance.
  595. *
  596. * @param int $per_page
  597. * @param array $columns
  598. * @return Paginator
  599. */
  600. public function paginate($per_page = 20, $columns = array('*'))
  601. {
  602. // Because some database engines may throw errors if we leave orderings
  603. // on the query when retrieving the total number of records, we'll drop
  604. // all of the ordreings and put them back on the query.
  605. list($orderings, $this->orderings) = array($this->orderings, null);
  606. $total = $this->count(reset($columns));
  607. $page = Paginator::page($total, $per_page);
  608. $this->orderings = $orderings;
  609. // Now we're ready to get the actual pagination results from the table
  610. // using the for_page and get methods. The "for_page" method provides
  611. // a convenient way to set the paging limit and offset.
  612. $results = $this->for_page($page, $per_page)->get($columns);
  613. return Paginator::make($results, $total, $per_page);
  614. }
  615. /**
  616. * Insert an array of values into the database table.
  617. *
  618. * @param array $values
  619. * @return bool
  620. */
  621. public function insert($values)
  622. {
  623. // Force every insert to be treated like a batch insert to make creating
  624. // the binding array simpler since we can just spin through the inserted
  625. // rows as if there/ was more than one every time.
  626. if ( ! is_array(reset($values))) $values = array($values);
  627. $bindings = array();
  628. // We need to merge the the insert values into the array of the query
  629. // bindings so that they will be bound to the PDO statement when it
  630. // is executed by the database connection.
  631. foreach ($values as $value)
  632. {
  633. $bindings = array_merge($bindings, array_values($value));
  634. }
  635. $sql = $this->grammar->insert($this, $values);
  636. return $this->connection->query($sql, $bindings);
  637. }
  638. /**
  639. * Insert an array of values into the database table and return the ID.
  640. *
  641. * @param array $values
  642. * @param string $sequence
  643. * @return int
  644. */
  645. public function insert_get_id($values, $sequence = null)
  646. {
  647. $sql = $this->grammar->insert($this, $values);
  648. $this->connection->query($sql, array_values($values));
  649. // Some database systems (Postgres) require a sequence name to be
  650. // given when retrieving the auto-incrementing ID, so we'll pass
  651. // the given sequence into the method just in case.
  652. return (int) $this->connection->pdo->lastInsertId($sequence);
  653. }
  654. /**
  655. * Increment the value of a column by a given amount.
  656. *
  657. * @param string $column
  658. * @param int $amount
  659. * @return int
  660. */
  661. public function increment($column, $amount = 1)
  662. {
  663. return $this->adjust($column, $amount, ' + ');
  664. }
  665. /**
  666. * Decrement the value of a column by a given amount.
  667. *
  668. * @param string $column
  669. * @param int $amount
  670. * @return int
  671. */
  672. public function decrement($column, $amount = 1)
  673. {
  674. return $this->adjust($column, $amount, ' - ');
  675. }
  676. /**
  677. * Adjust the value of a column up or down by a given amount.
  678. *
  679. * @param string $column
  680. * @param int $amount
  681. * @param string $operator
  682. * @return int
  683. */
  684. protected function adjust($column, $amount, $operator)
  685. {
  686. $wrapped = $this->grammar->wrap($column);
  687. // To make the adjustment to the column, we'll wrap the expression in an
  688. // Expression instance, which forces the adjustment to be injected into
  689. // the query as a string instead of bound.
  690. $value = Database::raw($wrapped.$operator.$amount);
  691. return $this->update(array($column => $value));
  692. }
  693. /**
  694. * Update an array of values in the database table.
  695. *
  696. * @param array $values
  697. * @return int
  698. */
  699. public function update($values)
  700. {
  701. // For update statements, we need to merge the bindings such that the update
  702. // values occur before the where bindings in the array since the sets will
  703. // precede any of the where clauses in the SQL syntax that is generated.
  704. $bindings = array_merge(array_values($values), $this->bindings);
  705. $sql = $this->grammar->update($this, $values);
  706. return $this->connection->query($sql, $bindings);
  707. }
  708. /**
  709. * Execute the query as a DELETE statement.
  710. *
  711. * Optionally, an ID may be passed to the method do delete a specific row.
  712. *
  713. * @param int $id
  714. * @return int
  715. */
  716. public function delete($id = null)
  717. {
  718. // If an ID is given to the method, we'll set the where clause to
  719. // match on the value of the ID. This allows the developer to
  720. // quickly delete a row by its primary key value.
  721. if ( ! is_null($id))
  722. {
  723. $this->where('id', '=', $id);
  724. }
  725. $sql = $this->grammar->delete($this);
  726. return $this->connection->query($sql, $this->bindings);
  727. }
  728. /**
  729. * Magic Method for handling dynamic functions.
  730. *
  731. * This method handles calls to aggregates as well as dynamic where clauses.
  732. */
  733. public function __call($method, $parameters)
  734. {
  735. if (strpos($method, 'where_') === 0)
  736. {
  737. return $this->dynamic_where($method, $parameters, $this);
  738. }
  739. // All of the aggregate methods are handled by a single method, so we'll
  740. // catch them all here and then pass them off to the agregate method
  741. // instead of creating methods for each one of them.
  742. if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
  743. {
  744. if (count($parameters) == 0) $parameters[0] = '*';
  745. return $this->aggregate(strtoupper($method), (array) $parameters[0]);
  746. }
  747. throw new \Exception("Method [$method] is not defined on the Query class.");
  748. }
  749. }