pickles/classes/Database/PDO/Common.php
2010-10-22 00:31:26 -04:00

267 lines
6.4 KiB
PHP

<?php
/**
* PDO Class File for PICKLES
*
* PHP version 5
*
* Licensed under The MIT License
* Redistribution of these files must retain the above copyright notice.
*
* @author Josh Sherman <josh@gravityblvd.com>
* @copyright Copyright 2007-2010, Gravity Boulevard, LLC
* @license http://www.opensource.org/licenses/mit-license.html
* @package PICKLES
* @link http://p.ickl.es
*/
/**
* PDO Abstraction Layer
*
* Parent class for any of our database classes that use PDO.
*/
class Database_PDO_Common extends Database_Common
{
/**
* DSN format
*
* @access protected
* @var string
*/
protected $dsn;
/**
* PDO Attributes
*
* @access protected
* @var string
*/
protected $attributes = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::NULL_EMPTY_STRING => true
);
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// Checks that the prefix is set
if ($this->dsn == null)
{
throw new Exception('Data source name is not defined');
}
}
/**
* Opens database connection
*
* Establishes a connection to the database based on the set configuration
* options.
*
* @return boolean true on success, throws an exception overwise
*/
public function open()
{
if ($this->connection === null)
{
if (isset($this->username, $this->password, $this->database))
{
// Creates a new PDO database object (persistent)
try
{
// Swaps out any variables with values in the DSN
$this->dsn = str_replace(
array('[[hostname]]', '[[port]]', '[[socket]]', '[[username]]', '[[password]]', '[[database]]'),
array($this->hostname, $this->port, $this->socket, $this->username, $this->password, $this->database),
$this->dsn
);
// Attempts to establish a connection
$this->connection = new PDO($this->dsn, $this->username, $this->password, $this->attributes);
}
catch (PDOException $e)
{
throw new Exception($e);
}
}
else
{
throw new Exception('There was an error loading the database configuration');
}
}
return true;
}
/**
* Closes database connection
*
* Sets the connection to null regardless of state.
*
* @return boolean always true
*/
public function close()
{
$this->connection = null;
return true;
}
/**
* Executes an SQL Statement
*
* Executes a standard or prepared query based on passed parameters. All
* queries are logged to a file as well as timed and logged in the
* execution time is over 1 second.
*
* @param string $sql statement to execute
* @param array $input_parameters optional key/values to be bound
* @return integer ID of the last inserted row or sequence number
*/
public function execute($sql, $input_parameters = null)
{
$this->open();
$loggable_query = $sql;
if ($input_parameters != null)
{
$loggable_query .= ' -- ' . (JSON_AVAILABLE ? json_encode($input_parameters) : serialize($input_parameters));
}
Log::query($loggable_query);
// Checks if the query is blank
if (trim($sql) != '')
{
try
{
// Establishes if the profiler is enabled
$profiler = (isset($this->config->pickles['profiler']) && $this->config->pickles['profiler'] != '' && preg_match('/^EXPLAIN /i', $sql) == false ? $this->config->pickles['profiler'] : false);
$explain = false;
// Executes a standard query
if ($input_parameters === null)
{
// Explains the query
if ($profiler === true || ((is_array($profiler) && in_array('explains', $profiler)) || stripos($profiler, 'explains') !== false))
{
$explain = $this->fetchAll('EXPLAIN ' . $sql);
}
$start_time = microtime(true);
$this->results = $this->connection->query($sql);
}
// Executes a prepared statement
else
{
// Explains the query
if ($profiler === true || ((is_array($profiler) && in_array('explains', $profiler)) || stripos($profiler, 'explains') !== false))
{
$explain = $this->fetchAll('EXPLAIN ' . $sql, $input_parameters);
}
$start_time = microtime(true);
$this->results = $this->connection->prepare($sql);
$this->results->execute($input_parameters);
}
$end_time = microtime(true);
$duration = $end_time - $start_time;
if ($duration >= 1)
{
Log::slowQuery($duration . ' seconds: ' . $loggable_query);
}
// Logs the information to the profiler
if ($profiler === true
|| ((is_array($profiler) && in_array('explains', $profiler))
|| stripos($profiler, 'explains') !== false)
|| ((is_array($profiler) && in_array('queries', $profiler))
|| stripos($profiler, 'queries') !== false))
{
Profiler::logQuery($sql, $input_parameters, $explain, $duration);
}
}
catch (PDOException $e)
{
throw new Exception($e);
}
}
else
{
throw new Exception('No query to execute');
}
return $this->connection->lastInsertId();
}
/**
* Fetch a single row from the database
*
* @param string $sql statement to be executed
* @param array $input_parameters optional key/values to be bound
* @param string $return_type optional type of return set
* @return mixed based on return type
*/
public function fetch($sql = null, $input_parameters = null, $return_type = null)
{
$this->open();
if ($sql !== null)
{
$this->execute($sql, $input_parameters);
}
// Pulls the results based on the type
$results = false;
switch ($return_type)
{
case 'column':
$results = $this->results->fetchColumn(0);
break;
case 'all':
$results = $this->results->fetchAll(PDO::FETCH_ASSOC);
break;
default:
$results = $this->results->fetch(PDO::FETCH_ASSOC);
break;
}
return $results;
}
/**
* Fetch a single column from the database
*
* This method assumes you want the first column in your select. If you
* need 2 or more columns you should simply use fetch().
*
* @param string $sql statement to be executed
* @param array $input_parameters optional key/values to be bound
* @return string
*/
public function fetchColumn($sql = null, $input_parameters = null)
{
return $this->fetch($sql, $input_parameters, 'column');
}
/**
* Fetches all rows as an array
*
* @param string $sql statement to be executed
* @param array $input_parameters optional key/values to be bound
* @return array
*/
public function fetchAll($sql = null, $input_parameters = null)
{
return $this->fetch($sql, $input_parameters, 'all');
}
}
?>