PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Illuminate/Database/Query/Builder.php

https://github.com/Fale/framework
PHP | 1234 lines | 446 code | 182 blank | 606 comment | 11 complexity | 83536d343bd15e022b8aa5fef2ef497c MD5 | raw file
  1. <?php namespace Illuminate\Database\Query;
  2. use Closure;
  3. use Illuminate\Database\ConnectionInterface;
  4. use Illuminate\Database\Query\Grammars\Grammar;
  5. use Illuminate\Database\Query\Processors\Processor;
  6. class Builder {
  7. /**
  8. * The database connection instance.
  9. *
  10. * @var Illuminate\Database\Connection
  11. */
  12. protected $connection;
  13. /**
  14. * The database query grammar instance.
  15. *
  16. * @var Illuminate\Database\Query\Grammars\Grammar
  17. */
  18. protected $grammar;
  19. /**
  20. * The database query post processor instance.
  21. *
  22. * @var Illuminate\Database\Query\Processors\Processor
  23. */
  24. protected $processor;
  25. /**
  26. * The current query value bindings.
  27. *
  28. * @var array
  29. */
  30. protected $bindings = array();
  31. /**
  32. * An aggregate function and column to be run.
  33. *
  34. * @var array
  35. */
  36. public $aggregate;
  37. /**
  38. * The columns that should be returned.
  39. *
  40. * @var array
  41. */
  42. public $columns;
  43. /**
  44. * Indicates if the query returns distinct results.
  45. *
  46. * @var bool
  47. */
  48. public $distinct = false;
  49. /**
  50. * The table which the query is targeting.
  51. *
  52. * @var string
  53. */
  54. public $from;
  55. /**
  56. * The table joins for the query.
  57. *
  58. * @var array
  59. */
  60. public $joins;
  61. /**
  62. * The where constraints for the query.
  63. *
  64. * @var array
  65. */
  66. public $wheres;
  67. /**
  68. * The groupings for the query.
  69. *
  70. * @var array
  71. */
  72. public $groups;
  73. /**
  74. * The having constraints for the query.
  75. *
  76. * @var array
  77. */
  78. public $havings;
  79. /**
  80. * The orderings for the query.
  81. *
  82. * @var array
  83. */
  84. public $orders;
  85. /**
  86. * The maximum number of records to return.
  87. *
  88. * @var int
  89. */
  90. public $limit;
  91. /**
  92. * The number of records to skip.
  93. *
  94. * @var int
  95. */
  96. public $offset;
  97. /**
  98. * All of the available clause operators.
  99. *
  100. * @var array
  101. */
  102. protected $operators = array(
  103. '=', '<', '>', '<=', '>=', '<>', '!=',
  104. 'like', 'not like', 'between',
  105. );
  106. /**
  107. * Create a new query builder instance.
  108. *
  109. * @param Illuminate\Database\ConnectionInterface $connection
  110. * @param Illuminate\Database\Query\Grammars\Grammar $grammar
  111. * @param Illuminate\Database\Query\Processors\Processor $processor
  112. * @return void
  113. */
  114. public function __construct(ConnectionInterface $connection,
  115. Grammar $grammar,
  116. Processor $processor)
  117. {
  118. $this->grammar = $grammar;
  119. $this->processor = $processor;
  120. $this->connection = $connection;
  121. }
  122. /**
  123. * Set the columns to be selected.
  124. *
  125. * @param array $columns
  126. * @return Illuminate\Database\Query\Builder
  127. */
  128. public function select($columns = array('*'))
  129. {
  130. $this->columns = is_array($columns) ? $columns : func_get_args();
  131. return $this;
  132. }
  133. /**
  134. * Force the query to only return distinct results.
  135. *
  136. * @return Illuminate\Database\Query\Builder
  137. */
  138. public function distinct()
  139. {
  140. $this->distinct = true;
  141. return $this;
  142. }
  143. /**
  144. * Set the table which the query is targeting.
  145. *
  146. * @param string $table
  147. * @return Illuminate\Database\Query\Builder
  148. */
  149. public function from($table)
  150. {
  151. $this->from = $table;
  152. return $this;
  153. }
  154. /**
  155. * Add a join clause to the query.
  156. *
  157. * @param string $table
  158. * @param string $first
  159. * @param string $operator
  160. * @param string $second
  161. * @param string $type
  162. * @return Illuminate\Database\Query\Builder
  163. */
  164. public function join($table, $first, $operator = null, $second = null, $type = 'inner')
  165. {
  166. // If the first "column" of the join is really a Closure instance the developer
  167. // is trying to build a join with a complex "on" clause containing more than
  168. // one condition, so we'll add the join and call a Closure with the query.
  169. if ($first instanceof Closure)
  170. {
  171. $this->joins[] = new JoinClause($type, $table);
  172. call_user_func($first, end($this->joins));
  173. }
  174. // If the column is simply a string, we can assume the join simply has a basic
  175. // "on" clause with a single condition. So we will just build the join with
  176. // this simple join clauses attached to it. There is not a join callback.
  177. else
  178. {
  179. $join = new JoinClause($type, $table);
  180. $join->on($first, $operator, $second);
  181. $this->joins[] = $join;
  182. }
  183. return $this;
  184. }
  185. /**
  186. * Add a left join to the query.
  187. *
  188. * @param string $table
  189. * @param string $first
  190. * @param string $operator
  191. * @param string $second
  192. * @return Illuminate\Database\Query\Builder
  193. */
  194. public function leftJoin($table, $first, $operator = null, $second = null)
  195. {
  196. return $this->join($table, $first, $operator, $second, 'left');
  197. }
  198. /**
  199. * Add a basic where clause to the query.
  200. *
  201. * @param string $column
  202. * @param string $operator
  203. * @param mixed $value
  204. * @param string $boolean
  205. * @return Illuminate\Database\Query\Builder
  206. */
  207. public function where($column, $operator = null, $value = null, $boolean = 'and')
  208. {
  209. // If the columns is actually a Closure instance, we will assume the developer
  210. // wants to begin a nested where statement which is wrapped in parenthesis.
  211. // We'll add that Closure to the query then return back out immediately.
  212. if ($column instanceof Closure)
  213. {
  214. return $this->whereNested($column, $boolean);
  215. }
  216. // If the given operator is not found in the list of valid operators we will
  217. // assume that the developer is just short-cutting the '=' operators and
  218. // we will set the operators to '=' and set the values appropriately.
  219. if ( ! in_array(strtolower($operator), $this->operators, true))
  220. {
  221. list($value, $operator) = array($operator, '=');
  222. }
  223. // If the value is a Closure, it means the developer is performing an entire
  224. // sub-select within the query and we will need to compile the sub-select
  225. // within the where clause to get the appropriate query record results.
  226. if ($value instanceof Closure)
  227. {
  228. return $this->whereSub($column, $operator, $value, $boolean);
  229. }
  230. // Now that we are working with just a simple query we can put the elements
  231. // in our array and add the query binding to our array of bindings that
  232. // will be bound to each SQL statements when it is finally executed.
  233. $type = 'Basic';
  234. $this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean');
  235. if ( ! $value instanceof Expression)
  236. {
  237. $this->bindings[] = $value;
  238. }
  239. return $this;
  240. }
  241. /**
  242. * Add an "or where" clause to the query.
  243. *
  244. * @param string $column
  245. * @param string $operator
  246. * @param mixed $value
  247. * @return Illuminate\Database\Query\Builder
  248. */
  249. public function orWhere($column, $operator = null, $value = null)
  250. {
  251. return $this->where($column, $operator, $value, 'or');
  252. }
  253. /**
  254. * Add a raw where clause to the query.
  255. *
  256. * @param string $sql
  257. * @param array $bindings
  258. * @param string $boolean
  259. * @return Illuminate\Database\Query\Builder
  260. */
  261. public function whereRaw($sql, array $bindings = array(), $boolean = 'and')
  262. {
  263. $type = 'raw';
  264. $this->wheres[] = compact('type', 'sql', 'boolean');
  265. $this->bindings = array_merge($this->bindings, $bindings);
  266. return $this;
  267. }
  268. /**
  269. * Add a raw or where clause to the query.
  270. *
  271. * @param string $sql
  272. * @param array $bindings
  273. * @return Illuminate\Database\Query\Builder
  274. */
  275. public function orWhereRaw($sql, array $bindings = array())
  276. {
  277. return $this->whereRaw($sql, $bindings, 'or');
  278. }
  279. /**
  280. * Add a where between statement to the query.
  281. *
  282. * @param string $column
  283. * @param array $values
  284. * @param string $boolean
  285. * @return Illuminate\Database\Query\Builder
  286. */
  287. public function whereBetween($column, array $values, $boolean = 'and')
  288. {
  289. $type = 'between';
  290. $this->wheres[] = compact('column', 'type', 'boolean');
  291. $this->bindings = array_merge($this->bindings, $values);
  292. return $this;
  293. }
  294. /**
  295. * Add an or where between statement to the query.
  296. *
  297. * @param string $column
  298. * @param array $values
  299. * @return Illuminate\Database\Query\Builder
  300. */
  301. public function orWhereBetween($column, array $values)
  302. {
  303. return $this->whereBetween($column, $values, 'or');
  304. }
  305. /**
  306. * Add a nested where statement to the query.
  307. *
  308. * @param Closure $callback
  309. * @param string $boolean
  310. * @return Illuminate\Database\Query\Builder
  311. */
  312. public function whereNested(Closure $callback, $boolean = 'and')
  313. {
  314. // To handle nested queries we'll actually create a brand new query instance
  315. // and pass it off to the Closure that we have. The Closure can simply do
  316. // do whatever it wants to a query then we will store it for compiling.
  317. $type = 'Nested';
  318. $query = $this->newQuery();
  319. $query->from($this->from);
  320. call_user_func($callback, $query);
  321. // Once we have let the Closure do its things, we can gather the bindings on
  322. // the nested query builder and merge them into these bindings since they
  323. // need to get extracted out of the children and assigned to the array.
  324. $this->wheres[] = compact('type', 'query', 'boolean');
  325. $this->mergeBindings($query);
  326. return $this;
  327. }
  328. /**
  329. * Add a full sub-select to the query.
  330. *
  331. * @param string $column
  332. * @param string $operator
  333. * @param Closure $callback
  334. * @param string $boolean
  335. * @return Illuminate\Database\Query\Builder
  336. */
  337. protected function whereSub($column, $operator, Closure $callback, $boolean)
  338. {
  339. $type = 'Sub';
  340. $query = $this->newQuery();
  341. // Once we have the query instance we can simply execute it so it can add all
  342. // of the sub-select's conditions to itself, and then we can cache it off
  343. // in the array of where clauses for the "main" parent query instance.
  344. call_user_func($callback, $query);
  345. $this->wheres[] = compact('type', 'column', 'operator', 'query', 'boolean');
  346. $this->mergeBindings($query);
  347. return $this;
  348. }
  349. /**
  350. * Add an exists clause to the query.
  351. *
  352. * @param Closure $callback
  353. * @param string $boolean
  354. * @param bool $not
  355. * @return Illuminate\Database\Query\Builder
  356. */
  357. public function whereExists(Closure $callback, $boolean = 'and', $not = false)
  358. {
  359. $type = $not ? 'NotExists' : 'Exists';
  360. $query = $this->newQuery();
  361. // Similar to the sub-select clause, we will create a new query instance so
  362. // the developer may cleanly specify the entire exists query and we will
  363. // compile the whole thing in the grammar and insert it into the SQL.
  364. call_user_func($callback, $query);
  365. $this->wheres[] = compact('type', 'operator', 'query', 'boolean');
  366. $this->mergeBindings($query);
  367. return $this;
  368. }
  369. /**
  370. * Add an or exists clause to the query.
  371. *
  372. * @param Closure $callback
  373. * @param bool $not
  374. * @return Illuminate\Database\Query\Builder
  375. */
  376. public function orWhereExists(Closure $callback, $not = false)
  377. {
  378. return $this->whereExists($callback, 'or', $not);
  379. }
  380. /**
  381. * Add a where not exists clause to the query.
  382. *
  383. * @param Closure $calback
  384. * @param string $boolean
  385. * @return Illuminate\Database\Query\Builder
  386. */
  387. public function whereNotExists(Closure $callback, $boolean = 'and')
  388. {
  389. return $this->whereExists($callback, $boolean, true);
  390. }
  391. /**
  392. * Add a where not exists clause to the query.
  393. *
  394. * @param Closure $calback
  395. * @return Illuminate\Database\Query\Builder
  396. */
  397. public function orWhereNotExists(Closure $callback)
  398. {
  399. return $this->orWhereExists($callback, true);
  400. }
  401. /**
  402. * Add a "where in" clause to the query.
  403. *
  404. * @param string $column
  405. * @param mixed $values
  406. * @param string $boolean
  407. * @param bool $not
  408. * @return Illuminate\Database\Query\Builder
  409. */
  410. public function whereIn($column, $values, $boolean = 'and', $not = false)
  411. {
  412. $type = $not ? 'NotIn' : 'In';
  413. // If the value of the where in clause is actually a Closure, we will assume that
  414. // the developer is using a full sub-select for this "in" statement, and will
  415. // execute those Closures, then we can re-construct the entire sub-selects.
  416. if ($values instanceof Closure)
  417. {
  418. return $this->whereInSub($column, $values, $boolean, $not);
  419. }
  420. $this->wheres[] = compact('type', 'column', 'values', 'boolean');
  421. $this->bindings = array_merge($this->bindings, $values);
  422. return $this;
  423. }
  424. /**
  425. * Add an "or where in" clause to the query.
  426. *
  427. * @param string $column
  428. * @param mixed $values
  429. * @param mixed $value
  430. * @return Illuminate\Database\Query\Builder
  431. */
  432. public function orWhereIn($column, $values)
  433. {
  434. return $this->whereIn($column, $values, 'or');
  435. }
  436. /**
  437. * Add a "where not in" clause to the query.
  438. *
  439. * @param string $column
  440. * @param mixed $values
  441. * @param string $boolean
  442. * @return Illuminate\Database\Query\Builder
  443. */
  444. public function whereNotIn($column, $values, $boolean = 'and')
  445. {
  446. return $this->whereIn($column, $values, $boolean, true);
  447. }
  448. /**
  449. * Add an "or where not in" clause to the query.
  450. *
  451. * @param string $column
  452. * @param mixed $values
  453. * @return Illuminate\Database\Query\Builder
  454. */
  455. public function orWhereNotIn($column, $values)
  456. {
  457. return $this->whereNotIn($column, $values, 'or');
  458. }
  459. /**
  460. * Add a where in with a sub-select to the query.
  461. *
  462. * @param string $column
  463. * @param Closure $callback
  464. * @param string $boolean
  465. * @param bool $not
  466. * @return Illuminate\Database\Query\Builder
  467. */
  468. protected function whereInSub($column, Closure $callback, $boolean, $not)
  469. {
  470. $type = $not ? 'NotInSub' : 'InSub';
  471. // To create the exists sub-select, we will actually create a query and call the
  472. // provided callback with the query so the developer may set any of the query
  473. // conditions they want for the in clause, then we'll put it in this array.
  474. call_user_func($callback, $query = $this->newQuery());
  475. $this->wheres[] = compact('type', 'column', 'query', 'boolean');
  476. $this->mergeBindings($query);
  477. return $this;
  478. }
  479. /**
  480. * Add a "where null" clause to the query.
  481. *
  482. * @param string $column
  483. * @param string $boolean
  484. * @param bool $not
  485. * @return Illuminate\Database\Query\Builder
  486. */
  487. public function whereNull($column, $boolean = 'and', $not = false)
  488. {
  489. $type = $not ? 'NotNull' : 'Null';
  490. $this->wheres[] = compact('type', 'column', 'boolean');
  491. return $this;
  492. }
  493. /**
  494. * Add an "or where null" clause to the query.
  495. *
  496. * @param string $column
  497. * @return Illuminate\Database\Query\Builder
  498. */
  499. public function orWhereNull($column)
  500. {
  501. return $this->whereNull($column, 'or');
  502. }
  503. /**
  504. * Add a "where not null" clause to the query.
  505. *
  506. * @param string $column
  507. * @param string $boolean
  508. * @return Illuminate\Database\Query\Builder
  509. */
  510. public function whereNotNull($column, $boolean = 'and')
  511. {
  512. return $this->whereNull($column, $boolean, true);
  513. }
  514. /**
  515. * Add an "or where not null" clause to the query.
  516. *
  517. * @param string $column
  518. * @return Illuminate\Database\Query\Builder
  519. */
  520. public function orWhereNotNull($column)
  521. {
  522. return $this->whereNotNull($column, 'or');
  523. }
  524. /**
  525. * Add a "group by" clause to the query.
  526. *
  527. * @param dynamic $columns
  528. * @return Illuminate\Database\Query\Builder
  529. */
  530. public function groupBy()
  531. {
  532. $this->groups = array_merge((array) $this->groups, func_get_args());
  533. return $this;
  534. }
  535. /**
  536. * Add a "having" clause to the query.
  537. *
  538. * @param string $column
  539. * @param string $operator
  540. * @param string $value
  541. * @return Illuminate\Database\Query\Builder
  542. */
  543. public function having($column, $operator = null, $value = null)
  544. {
  545. $this->havings[] = compact('column', 'operator', 'value');
  546. $this->bindings[] = $value;
  547. return $this;
  548. }
  549. /**
  550. * Add an "order by" clause to the query.
  551. *
  552. * @param string $column
  553. * @param string $direction
  554. * @return Illuminate\Database\Query\Builder
  555. */
  556. public function orderBy($column, $direction = 'asc')
  557. {
  558. $this->orders[] = compact('column', 'direction');
  559. return $this;
  560. }
  561. /**
  562. * Set the "offset" value of the query.
  563. *
  564. * @param int $value
  565. * @return Illuminate\Database\Query\Builder
  566. */
  567. public function skip($value)
  568. {
  569. $this->offset = $value;
  570. return $this;
  571. }
  572. /**
  573. * Set the "limit" value of the query.
  574. *
  575. * @param int $value
  576. * @return Illuminate\Database\Query\Builder
  577. */
  578. public function take($value)
  579. {
  580. $this->limit = $value;
  581. return $this;
  582. }
  583. /**
  584. * Set the limit and offset for a given page.
  585. *
  586. * @param int $page
  587. * @param int $perPage
  588. * @return Illuminate\Database\Query\Builder
  589. */
  590. public function forPage($page, $perPage = 15)
  591. {
  592. return $this->skip(($page - 1) * $perPage)->take($perPage);
  593. }
  594. /**
  595. * Get the SQL representation of the query.
  596. *
  597. * @return string
  598. */
  599. public function toSql()
  600. {
  601. return $this->grammar->compileSelect($this);
  602. }
  603. /**
  604. * Execute a query for a single record by ID.
  605. *
  606. * @param int $id
  607. * @param array $columns
  608. * @return mixed
  609. */
  610. public function find($id, $columns = array('*'))
  611. {
  612. return $this->where('id', '=', $id)->first($columns);
  613. }
  614. /**
  615. * Pluck a single column from the database.
  616. *
  617. * @param string $column
  618. * @return mixed
  619. */
  620. public function pluck($column)
  621. {
  622. $result = (array) $this->first(array($column));
  623. return count($result) > 0 ? reset($result) : null;
  624. }
  625. /**
  626. * Execute the query and get the first result.
  627. *
  628. * @param array $columns
  629. * @return mixed
  630. */
  631. public function first($columns = array('*'))
  632. {
  633. $results = $this->take(1)->get($columns);
  634. return count($results) > 0 ? reset($results) : null;
  635. }
  636. /**
  637. * Execute the query as a "select" statement.
  638. *
  639. * @param array $columns
  640. * @return array
  641. */
  642. public function get($columns = array('*'))
  643. {
  644. // If no columns have been specified for the select statement, we will set them
  645. // here to either the passed columns, or the standard default of retrieving
  646. // all of the columns on the table using the "wildcard" column character.
  647. if (is_null($this->columns))
  648. {
  649. $this->columns = $columns;
  650. }
  651. $results = $this->connection->select($this->toSql(), $this->bindings);
  652. $this->processor->processSelect($this, $results);
  653. return $results;
  654. }
  655. /**
  656. * Get an array with the values of a given column.
  657. *
  658. * @param string $column
  659. * @param string $key
  660. * @return array
  661. */
  662. public function lists($column, $key = null)
  663. {
  664. $columns = is_null($key) ? array($column) : array($column, $key);
  665. // First we will just get all of the column values for the record result set
  666. // then we can associate those values with the column if it was specified
  667. // otherwise we can just give these values back without a specific key.
  668. $values = array_map(function($row) use ($column)
  669. {
  670. $row = (object) $row;
  671. return $row->$column;
  672. }, $results = $this->get($columns));
  673. // If a key was specified and we have results, we will go ahead and combine
  674. // the values with the keys of all of the records so that the values can
  675. // be accessed by the key of the rows instead of simply being numeric.
  676. if ( ! is_null($key) and count($results) > 0)
  677. {
  678. return array_combine(array_map(function($row) use ($key)
  679. {
  680. $row = (object) $row;
  681. return $row->$key;
  682. }, $results), $values);
  683. }
  684. return $values;
  685. }
  686. /**
  687. * Get a paginator for the "select" statement.
  688. *
  689. * @param int $perPage
  690. * @param array $columns
  691. * @return Illuminate\Pagination\Paginator
  692. */
  693. public function paginate($perPage = 15, $columns = array('*'))
  694. {
  695. $paginator = $this->connection->getPaginator();
  696. if (isset($this->groups))
  697. {
  698. return $this->groupedPaginate($paginator, $perPage, $columns);
  699. }
  700. else
  701. {
  702. return $this->ungroupedPaginate($paginator, $perPage, $columns);
  703. }
  704. }
  705. /**
  706. * Create a paginator for a grouped pagination statement.
  707. *
  708. * @param Illuminate\Pagination\Environment $paginator
  709. * @param int $perPage
  710. * @param array $columns
  711. * @return Illuminate\Pagination\Paginator
  712. */
  713. protected function groupedPaginate($paginator, $perPage, $columns)
  714. {
  715. $results = $this->get($columns);
  716. return $this->buildRawPaginator($paginator, $results, $perPage);
  717. }
  718. /**
  719. * Build a paginator instance from a raw result array.
  720. *
  721. * @param Illuminate\Pagination\Environment $paginator
  722. * @param array $results
  723. * @param int $perPage
  724. * @return Illuminate\Pagination\Paginator
  725. */
  726. public function buildRawPaginator($paginator, $results, $perPage)
  727. {
  728. // For queries which have a group by, we will actually retrieve the entire set
  729. // of rows from the table and "slice" them via PHP. This is inefficient and
  730. // the developer must be aware of this behavior; however, it's an option.
  731. $start = ($paginator->getCurrentPage() - 1) * $perPage;
  732. $sliced = array_slice($results, $start, $perPage);
  733. return $paginator->make($sliced, count($results), $perPage);
  734. }
  735. /**
  736. * Create a paginator for an un-grouped pagination statement.
  737. *
  738. * @param Illuminate\Pagination\Environment $paginator
  739. * @param int $perPage
  740. * @param array $columns
  741. * @return Illuminate\Pagination\Paginator
  742. */
  743. protected function ungroupedPaginate($paginator, $perPage, $columns)
  744. {
  745. $total = $this->getPaginationCount();
  746. // Once we have the total number of records to be paginated, we can grab the
  747. // current page and the result array. Then we are ready to create a brand
  748. // new Paginator instances for the results which will create the links.
  749. $page = $paginator->getCurrentPage();
  750. $results = $this->forPage($page, $perPage)->get($columns);
  751. return $paginator->make($results, $total, $perPage);
  752. }
  753. /**
  754. * Get the count of the total records for pagination.
  755. *
  756. * @return int
  757. */
  758. public function getPaginationCount()
  759. {
  760. list($orders, $this->orders) = array($this->orders, null);
  761. // Because some database engines may throw errors if we leave the ordering
  762. // statements on the query, we will "back them up" and remove them from
  763. // the query. Once we have the count we will put them back onto this.
  764. $total = $this->count();
  765. $this->orders = $orders;
  766. return $total;
  767. }
  768. /**
  769. * Determine if any rows exist for the current query.
  770. *
  771. * @return bool
  772. */
  773. public function exists()
  774. {
  775. return $this->count() > 0;
  776. }
  777. /**
  778. * Retrieve the "count" result of the query.
  779. *
  780. * @param string $column
  781. * @return int
  782. */
  783. public function count($column = '*')
  784. {
  785. return $this->aggregate(__FUNCTION__, array($column));
  786. }
  787. /**
  788. * Retrieve the minimum value of a given column.
  789. *
  790. * @param string $column
  791. * @return mixed
  792. */
  793. public function min($column)
  794. {
  795. return $this->aggregate(__FUNCTION__, array($column));
  796. }
  797. /**
  798. * Retrieve the maximum value of a given column.
  799. *
  800. * @param string $column
  801. * @return mixed
  802. */
  803. public function max($column)
  804. {
  805. return $this->aggregate(__FUNCTION__, array($column));
  806. }
  807. /**
  808. * Retrieve the sum of the values of a given column.
  809. *
  810. * @param string $column
  811. * @return mixed
  812. */
  813. public function sum($column)
  814. {
  815. return $this->aggregate(__FUNCTION__, array($column));
  816. }
  817. /**
  818. * Execute an aggregate function on the database.
  819. *
  820. * @param string $function
  821. * @param array $columns
  822. * @return mixed
  823. */
  824. public function aggregate($function, $columns = array('*'))
  825. {
  826. $this->aggregate = compact('function', 'columns');
  827. $results = $this->get($columns);
  828. // Once we have executed the query, we will reset the aggregate property so
  829. // that more select queries can be executed against the database without
  830. // the aggregate value getting in the way when the grammar builds it.
  831. $this->aggregate = null;
  832. $result = (array) $results[0];
  833. return $result['aggregate'];
  834. }
  835. /**
  836. * Insert a new record into the database.
  837. *
  838. * @param array $values
  839. * @return bool
  840. */
  841. public function insert(array $values)
  842. {
  843. // Since every insert gets treated like a batch insert, we will make sure the
  844. // bindings are structured in a way that is convenient for building these
  845. // inserts statements by verifying the elements are actually an array.
  846. if ( ! is_array(reset($values)))
  847. {
  848. $values = array($values);
  849. }
  850. $bindings = array();
  851. // We'll treat every insert like a batch insert so we can easily insert each
  852. // of the records into the database consistently. This will make it much
  853. // easier on the grammars to just handle one type of record insertion.
  854. foreach ($values as $record)
  855. {
  856. $bindings = array_merge($bindings, array_values($record));
  857. }
  858. $sql = $this->grammar->compileInsert($this, $values);
  859. // Once we have compiled the insert statement's SQL we can execute it on the
  860. // connection and return a result as a boolean success indicator as that
  861. // is the same type of result returned by the raw connection instance.
  862. $bindings = $this->cleanBindings($bindings);
  863. return $this->connection->insert($sql, $bindings);
  864. }
  865. /**
  866. * Insert a new record and get the value of the primary key.
  867. *
  868. * @param array $values
  869. * @param string $sequence
  870. * @return int
  871. */
  872. public function insertGetId(array $values, $sequence = null)
  873. {
  874. $sql = $this->grammar->compileInsertGetId($this, $values, $sequence);
  875. $values = $this->cleanBindings($values);
  876. return $this->processor->processInsertGetId($this, $sql, $values, $sequence);
  877. }
  878. /**
  879. * Update a record in the database.
  880. *
  881. * @param array $values
  882. * @return int
  883. */
  884. public function update(array $values)
  885. {
  886. $bindings = array_values(array_merge($values, $this->bindings));
  887. $sql = $this->grammar->compileUpdate($this, $values);
  888. return $this->connection->update($sql, $this->cleanBindings($bindings));
  889. }
  890. /**
  891. * Increment a column's value by a given amount.
  892. *
  893. * @param string $column
  894. * @param int $amount
  895. * @return int
  896. */
  897. public function increment($column, $amount = 1)
  898. {
  899. $wrapped = $this->grammar->wrap($column);
  900. return $this->update(array($column => $this->raw("$wrapped + $amount")));
  901. }
  902. /**
  903. * Decrement a column's value by a given amount.
  904. *
  905. * @param string $column
  906. * @param int $amount
  907. * @return int
  908. */
  909. public function decrement($column, $amount = 1)
  910. {
  911. $wrapped = $this->grammar->wrap($column);
  912. return $this->update(array($column => $this->raw("$wrapped - $amount")));
  913. }
  914. /**
  915. * Delete a record from the database.
  916. *
  917. * @param array $values
  918. * @return int
  919. */
  920. public function delete($id = null)
  921. {
  922. // If an ID is passed to the method, we will set the where clause to check
  923. // the ID to allow developers to simply and quickly remove a single row
  924. // from their database without manually specifying the where clauses.
  925. if ( ! is_null($id)) $this->where('id', '=', $id);
  926. $sql = $this->grammar->compileDelete($this);
  927. return $this->connection->delete($sql, $this->bindings);
  928. }
  929. /**
  930. * Run a truncate statement on the table.
  931. *
  932. * @return void
  933. */
  934. public function truncate()
  935. {
  936. foreach ($this->grammar->compileTruncate($this) as $sql => $bindings)
  937. {
  938. $this->connection->statement($sql, $bindings);
  939. }
  940. }
  941. /**
  942. * Get a new instance of the query builder.
  943. *
  944. * @return Illuminate\Database\Query\Builder
  945. */
  946. public function newQuery()
  947. {
  948. return new Builder($this->connection, $this->grammar, $this->processor);
  949. }
  950. /**
  951. * Merge an array of where clauses and bindings.
  952. *
  953. * @param array $wheres
  954. * @param array $bindings
  955. * @return void
  956. */
  957. public function mergeWheres($wheres, $bindings)
  958. {
  959. $this->wheres = array_merge($this->wheres, (array) $wheres);
  960. $this->bindings = array_values(array_merge($this->bindings, (array) $bindings));
  961. }
  962. /**
  963. * Get a copy of the where clauses and bindings in an array.
  964. *
  965. * @return array
  966. */
  967. public function getAndResetWheres()
  968. {
  969. $values = array($this->wheres, $this->bindings);
  970. list($this->wheres, $this->bindings) = array(null, array());
  971. return $values;
  972. }
  973. /**
  974. * Remove all of the expressions from a list of bindings.
  975. *
  976. * @param array $bindings
  977. * @return array
  978. */
  979. protected function cleanBindings(array $bindings)
  980. {
  981. return array_values(array_filter($bindings, function($binding)
  982. {
  983. return ! $binding instanceof Expression;
  984. }));
  985. }
  986. /**
  987. * Create a raw database expression.
  988. *
  989. * @param mixed $value
  990. * @return Illuminate\Database\Query\Expression
  991. */
  992. public function raw($value)
  993. {
  994. return $this->connection->raw($value);
  995. }
  996. /**
  997. * Get the current query value bindings.
  998. *
  999. * @return array
  1000. */
  1001. public function getBindings()
  1002. {
  1003. return $this->bindings;
  1004. }
  1005. /**
  1006. * Set the bindings on the query builder.
  1007. *
  1008. * @param array $bindings
  1009. * @return void
  1010. */
  1011. public function setBindings(array $bindings)
  1012. {
  1013. $this->bindings = $bindings;
  1014. }
  1015. /**
  1016. * Merge an array of bindings into our bindings.
  1017. *
  1018. * @param Illuminate\Database\Query\Builder $query
  1019. * @return void
  1020. */
  1021. public function mergeBindings(Builder $query)
  1022. {
  1023. $this->bindings = array_values(array_merge($this->bindings, $query->bindings));
  1024. }
  1025. /**
  1026. * Get the database connection instance.
  1027. *
  1028. * @return Illuminate\Database\ConnectionInterface
  1029. */
  1030. public function getConnection()
  1031. {
  1032. return $this->connection;
  1033. }
  1034. /**
  1035. * Get the database query processor instance.
  1036. *
  1037. * @return Illuminate\Database\Query\Processors\Processor
  1038. */
  1039. public function getProcessor()
  1040. {
  1041. return $this->processor;
  1042. }
  1043. /**
  1044. * Get the query grammar instance.
  1045. *
  1046. * @return Illuminate\Database\Grammar
  1047. */
  1048. public function getGrammar()
  1049. {
  1050. return $this->grammar;
  1051. }
  1052. }