123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- <?php namespace Laravel\Database;
- use PDO, PDOStatement, Laravel\Config, Laravel\Event;
- class Connection {
- /**
- * The raw PDO connection instance.
- *
- * @var PDO
- */
- public $pdo;
- /**
- * The connection configuration array.
- *
- * @var array
- */
- public $config;
- /**
- * The query grammar instance for the connection.
- *
- * @var Grammars\Grammar
- */
- protected $grammar;
- /**
- * All of the queries that have been executed on all connections.
- *
- * @var array
- */
- public static $queries = array();
- /**
- * Create a new database connection instance.
- *
- * @param PDO $pdo
- * @param array $config
- * @return void
- */
- public function __construct(PDO $pdo, $config)
- {
- $this->pdo = $pdo;
- $this->config = $config;
- }
- /**
- * Begin a fluent query against a table.
- *
- * <code>
- * // Start a fluent query against the "users" table
- * $query = DB::connection()->table('users');
- *
- * // Start a fluent query against the "users" table and get all the users
- * $users = DB::connection()->table('users')->get();
- * </code>
- *
- * @param string $table
- * @return Query
- */
- public function table($table)
- {
- return new Query($this, $this->grammar(), $table);
- }
- /**
- * Create a new query grammar for the connection.
- *
- * @return Query\Grammars\Grammar
- */
- protected function grammar()
- {
- if (isset($this->grammar)) return $this->grammar;
- if (isset(\Laravel\Database::$registrar[$this->driver()]))
- {
- \Laravel\Database::$registrar[$this->driver()]['query']();
- }
- switch ($this->driver())
- {
- case 'mysql':
- return $this->grammar = new Query\Grammars\MySQL($this);
- case 'sqlite':
- return $this->grammar = new Query\Grammars\SQLite($this);
- case 'sqlsrv':
- return $this->grammar = new Query\Grammars\SQLServer($this);
- default:
- return $this->grammar = new Query\Grammars\Grammar($this);
- }
- }
- /**
- * Execute a callback wrapped in a database transaction.
- *
- * @param callback $callback
- * @return void
- */
- public function transaction($callback)
- {
- $this->pdo->beginTransaction();
- // After beginning the database transaction, we will call the callback
- // so that it can do its database work. If an exception occurs we'll
- // rollback the transaction and re-throw back to the developer.
- try
- {
- call_user_func($callback);
- }
- catch (\Exception $e)
- {
- $this->pdo->rollBack();
- throw $e;
- }
- $this->pdo->commit();
- }
- /**
- * Execute a SQL query against the connection and return a single column result.
- *
- * <code>
- * // Get the total number of rows on a table
- * $count = DB::connection()->only('select count(*) from users');
- *
- * // Get the sum of payment amounts from a table
- * $sum = DB::connection()->only('select sum(amount) from payments')
- * </code>
- *
- * @param string $sql
- * @param array $bindings
- * @return mixed
- */
- public function only($sql, $bindings = array())
- {
- $results = (array) $this->first($sql, $bindings);
- return reset($results);
- }
- /**
- * Execute a SQL query against the connection and return the first result.
- *
- * <code>
- * // Execute a query against the database connection
- * $user = DB::connection()->first('select * from users');
- *
- * // Execute a query with bound parameters
- * $user = DB::connection()->first('select * from users where id = ?', array($id));
- * </code>
- *
- * @param string $sql
- * @param array $bindings
- * @return object
- */
- public function first($sql, $bindings = array())
- {
- if (count($results = $this->query($sql, $bindings)) > 0)
- {
- return $results[0];
- }
- }
- /**
- * Execute a SQL query and return an array of StdClass objects.
- *
- * @param string $sql
- * @param array $bindings
- * @return array
- */
- public function query($sql, $bindings = array())
- {
- $sql = trim($sql);
- list($statement, $result) = $this->execute($sql, $bindings);
- // The result we return depends on the type of query executed against the
- // database. On SELECT clauses, we will return the result set, for update
- // and deletes we will return the affected row count.
- if (stripos($sql, 'select') === 0)
- {
- return $this->fetch($statement, Config::get('database.fetch'));
- }
- elseif (stripos($sql, 'update') === 0 or stripos($sql, 'delete') === 0)
- {
- return $statement->rowCount();
- }
- else
- {
- return $result;
- }
- }
- /**
- * Execute a SQL query against the connection.
- *
- * The PDO statement and boolean result will be return in an array.
- *
- * @param string $sql
- * @param array $bindings
- * @return array
- */
- protected function execute($sql, $bindings = array())
- {
- $bindings = (array) $bindings;
- // Since expressions are injected into the query as strings, we need to
- // remove them from the array of bindings. After we have removed them,
- // we'll reset the array so there are not gaps within the keys.
- $bindings = array_filter($bindings, function($binding)
- {
- return ! $binding instanceof Expression;
- });
- $bindings = array_values($bindings);
- $sql = $this->grammar()->shortcut($sql, $bindings);
- // Next we need to translate all DateTime bindings to their date-time
- // strings that are compatible with the database. Each grammar may
- // define it's own date-time format according to its needs.
- $datetime = $this->grammar()->datetime;
- for ($i = 0; $i < count($bindings); $i++)
- {
- if ($bindings[$i] instanceof \DateTime)
- {
- $bindings[$i] = $bindings[$i]->format($datetime);
- }
- }
- // Each database operation is wrapped in a try / catch so we can wrap
- // any database exceptions in our custom exception class, which will
- // set the message to include the SQL and query bindings.
- try
- {
- $statement = $this->pdo->prepare($sql);
- $start = microtime(true);
- $result = $statement->execute($bindings);
- }
- // If an exception occurs, we'll pass it into our custom exception
- // and set the message to include the SQL and query bindings so
- // debugging is much easier on the developer.
- catch (\Exception $exception)
- {
- $exception = new Exception($sql, $bindings, $exception);
- throw $exception;
- }
- // Once we have execute the query, we log the SQL, bindings, and
- // execution time in a static array that is accessed by all of
- // the connections actively being used by the application.
- if (Config::get('database.profile'))
- {
- $this->log($sql, $bindings, $start);
- }
- return array($statement, $result);
- }
- /**
- * Fetch all of the rows for a given statement.
- *
- * @param PDOStatement $statement
- * @param int $style
- * @return array
- */
- protected function fetch($statement, $style)
- {
- // If the fetch style is "class", we'll hydrate an array of PHP
- // stdClass objects as generic containers for the query rows,
- // otherwise we'll just use the fetch styel value.
- if ($style === PDO::FETCH_CLASS)
- {
- return $statement->fetchAll(PDO::FETCH_CLASS, 'stdClass');
- }
- else
- {
- return $statement->fetchAll($style);
- }
- }
- /**
- * Log the query and fire the core query event.
- *
- * @param string $sql
- * @param array $bindings
- * @param int $start
- * @return void
- */
- protected function log($sql, $bindings, $start)
- {
- $time = number_format((microtime(true) - $start) * 1000, 2);
- Event::fire('laravel.query', array($sql, $bindings, $time));
- static::$queries[] = compact('sql', 'bindings', 'time');
- }
- /**
- * Get the driver name for the database connection.
- *
- * @return string
- */
- public function driver()
- {
- return $this->config['driver'];
- }
- /**
- * Magic Method for dynamically beginning queries on database tables.
- */
- public function __call($method, $parameters)
- {
- return $this->table($method);
- }
- }
|