connection.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <?php namespace Laravel\Database;
  2. use PDO, PDOStatement, Laravel\Config, Laravel\Event;
  3. class Connection {
  4. /**
  5. * The raw PDO connection instance.
  6. *
  7. * @var PDO
  8. */
  9. public $pdo;
  10. /**
  11. * The connection configuration array.
  12. *
  13. * @var array
  14. */
  15. public $config;
  16. /**
  17. * The query grammar instance for the connection.
  18. *
  19. * @var Query\Grammars\Grammar
  20. */
  21. protected $grammar;
  22. /**
  23. * All of the queries that have been executed on all connections.
  24. *
  25. * @var array
  26. */
  27. public static $queries = array();
  28. /**
  29. * Create a new database connection instance.
  30. *
  31. * @param PDO $pdo
  32. * @param array $config
  33. * @return void
  34. */
  35. public function __construct(PDO $pdo, $config)
  36. {
  37. $this->pdo = $pdo;
  38. $this->config = $config;
  39. }
  40. /**
  41. * Begin a fluent query against a table.
  42. *
  43. * <code>
  44. * // Start a fluent query against the "users" table
  45. * $query = DB::connection()->table('users');
  46. *
  47. * // Start a fluent query against the "users" table and get all the users
  48. * $users = DB::connection()->table('users')->get();
  49. * </code>
  50. *
  51. * @param string $table
  52. * @return Query
  53. */
  54. public function table($table)
  55. {
  56. return new Query($this, $this->grammar(), $table);
  57. }
  58. /**
  59. * Create a new query grammar for the connection.
  60. *
  61. * @return Query\Grammars\Grammar
  62. */
  63. protected function grammar()
  64. {
  65. if (isset($this->grammar)) return $this->grammar;
  66. if (isset(\Laravel\Database::$registrar[$this->driver()]))
  67. {
  68. $resolver = \Laravel\Database::$registrar[$this->driver()]['query'];
  69. return $this->grammar = $resolver($this);
  70. }
  71. switch ($this->driver())
  72. {
  73. case 'mysql':
  74. return $this->grammar = new Query\Grammars\MySQL($this);
  75. case 'sqlite':
  76. return $this->grammar = new Query\Grammars\SQLite($this);
  77. case 'sqlsrv':
  78. return $this->grammar = new Query\Grammars\SQLServer($this);
  79. case 'pgsql':
  80. return $this->grammar = new Query\Grammars\Postgres($this);
  81. default:
  82. return $this->grammar = new Query\Grammars\Grammar($this);
  83. }
  84. }
  85. /**
  86. * Execute a callback wrapped in a database transaction.
  87. *
  88. * @param callback $callback
  89. * @return bool
  90. */
  91. public function transaction($callback)
  92. {
  93. $this->pdo->beginTransaction();
  94. // After beginning the database transaction, we will call the callback
  95. // so that it can do its database work. If an exception occurs we'll
  96. // rollback the transaction and re-throw back to the developer.
  97. try
  98. {
  99. call_user_func($callback);
  100. }
  101. catch (\Exception $e)
  102. {
  103. $this->pdo->rollBack();
  104. throw $e;
  105. }
  106. return $this->pdo->commit();
  107. }
  108. /**
  109. * Execute a SQL query against the connection and return a single column result.
  110. *
  111. * <code>
  112. * // Get the total number of rows on a table
  113. * $count = DB::connection()->only('select count(*) from users');
  114. *
  115. * // Get the sum of payment amounts from a table
  116. * $sum = DB::connection()->only('select sum(amount) from payments')
  117. * </code>
  118. *
  119. * @param string $sql
  120. * @param array $bindings
  121. * @return mixed
  122. */
  123. public function only($sql, $bindings = array())
  124. {
  125. $results = (array) $this->first($sql, $bindings);
  126. return reset($results);
  127. }
  128. /**
  129. * Execute a SQL query against the connection and return the first result.
  130. *
  131. * <code>
  132. * // Execute a query against the database connection
  133. * $user = DB::connection()->first('select * from users');
  134. *
  135. * // Execute a query with bound parameters
  136. * $user = DB::connection()->first('select * from users where id = ?', array($id));
  137. * </code>
  138. *
  139. * @param string $sql
  140. * @param array $bindings
  141. * @return object
  142. */
  143. public function first($sql, $bindings = array())
  144. {
  145. if (count($results = $this->query($sql, $bindings)) > 0)
  146. {
  147. return $results[0];
  148. }
  149. }
  150. /**
  151. * Execute a SQL query and return an array of StdClass objects.
  152. *
  153. * @param string $sql
  154. * @param array $bindings
  155. * @return array
  156. */
  157. public function query($sql, $bindings = array())
  158. {
  159. $sql = trim($sql);
  160. list($statement, $result) = $this->execute($sql, $bindings);
  161. // The result we return depends on the type of query executed against the
  162. // database. On SELECT clauses, we will return the result set, for update
  163. // and deletes we will return the affected row count.
  164. if (stripos($sql, 'select') === 0 || stripos($sql, 'show') === 0)
  165. {
  166. return $this->fetch($statement, Config::get('database.fetch'));
  167. }
  168. elseif (stripos($sql, 'update') === 0 or stripos($sql, 'delete') === 0)
  169. {
  170. return $statement->rowCount();
  171. }
  172. // For insert statements that use the "returning" clause, which is allowed
  173. // by database systems such as Postgres, we need to actually return the
  174. // real query result so the consumer can get the ID.
  175. elseif (stripos($sql, 'insert') === 0 and stripos($sql, 'returning') !== false)
  176. {
  177. return $this->fetch($statement, Config::get('database.fetch'));
  178. }
  179. else
  180. {
  181. return $result;
  182. }
  183. }
  184. /**
  185. * Execute a SQL query against the connection.
  186. *
  187. * The PDO statement and boolean result will be returned in an array.
  188. *
  189. * @param string $sql
  190. * @param array $bindings
  191. * @return array
  192. */
  193. protected function execute($sql, $bindings = array())
  194. {
  195. $bindings = (array) $bindings;
  196. // Since expressions are injected into the query as strings, we need to
  197. // remove them from the array of bindings. After we have removed them,
  198. // we'll reset the array so there are not gaps within the keys.
  199. $bindings = array_filter($bindings, function($binding)
  200. {
  201. return ! $binding instanceof Expression;
  202. });
  203. $bindings = array_values($bindings);
  204. $sql = $this->grammar()->shortcut($sql, $bindings);
  205. // Next we need to translate all DateTime bindings to their date-time
  206. // strings that are compatible with the database. Each grammar may
  207. // define it's own date-time format according to its needs.
  208. $datetime = $this->grammar()->datetime;
  209. for ($i = 0; $i < count($bindings); $i++)
  210. {
  211. if ($bindings[$i] instanceof \DateTime)
  212. {
  213. $bindings[$i] = $bindings[$i]->format($datetime);
  214. }
  215. }
  216. // Each database operation is wrapped in a try / catch so we can wrap
  217. // any database exceptions in our custom exception class, which will
  218. // set the message to include the SQL and query bindings.
  219. try
  220. {
  221. $statement = $this->pdo->prepare($sql);
  222. $start = microtime(true);
  223. $result = $statement->execute($bindings);
  224. }
  225. // If an exception occurs, we'll pass it into our custom exception
  226. // and set the message to include the SQL and query bindings so
  227. // debugging is much easier on the developer.
  228. catch (\Exception $exception)
  229. {
  230. $exception = new Exception($sql, $bindings, $exception);
  231. throw $exception;
  232. }
  233. // Once we have executed the query, we log the SQL, bindings, and
  234. // execution time in a static array that is accessed by all of
  235. // the connections actively being used by the application.
  236. if (Config::get('database.profile'))
  237. {
  238. $this->log($sql, $bindings, $start);
  239. }
  240. return array($statement, $result);
  241. }
  242. /**
  243. * Fetch all of the rows for a given statement.
  244. *
  245. * @param PDOStatement $statement
  246. * @param int $style
  247. * @return array
  248. */
  249. protected function fetch($statement, $style)
  250. {
  251. // If the fetch style is "class", we'll hydrate an array of PHP
  252. // stdClass objects as generic containers for the query rows,
  253. // otherwise we'll just use the fetch style value.
  254. if ($style === PDO::FETCH_CLASS)
  255. {
  256. return $statement->fetchAll(PDO::FETCH_CLASS, 'stdClass');
  257. }
  258. else
  259. {
  260. return $statement->fetchAll($style);
  261. }
  262. }
  263. /**
  264. * Log the query and fire the core query event.
  265. *
  266. * @param string $sql
  267. * @param array $bindings
  268. * @param int $start
  269. * @return void
  270. */
  271. protected function log($sql, $bindings, $start)
  272. {
  273. $time = (microtime(true) - $start) * 1000;
  274. Event::fire('laravel.query', array($sql, $bindings, $time));
  275. static::$queries[] = compact('sql', 'bindings', 'time');
  276. }
  277. /**
  278. * Get the driver name for the database connection.
  279. *
  280. * @return string
  281. */
  282. public function driver()
  283. {
  284. return $this->config['driver'];
  285. }
  286. /**
  287. * Magic Method for dynamically beginning queries on database tables.
  288. */
  289. public function __call($method, $parameters)
  290. {
  291. return $this->table($method);
  292. }
  293. }