Skip to content

Instantly share code, notes, and snippets.

@tkdave
Created February 9, 2012 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tkdave/1783826 to your computer and use it in GitHub Desktop.
Save tkdave/1783826 to your computer and use it in GitHub Desktop.
Memcache-backed MySQL Database connection class.
<?php
/**
* Lazy Database connection class - API version
*
* The database is not actually opened until we execute a query
*
* @author David Knape
*/
class DBConnection
{
public $databaseHost = "localhost";
public $databaseUser = "root";
public $databasePass = "";
public $databaseName = "";
protected $connected = false;
protected $memcache;
protected $memcacheHost;
protected $memcachePort;
protected $memcacheConnected = false;
public $debugLogEnabled = false;
public $debugLogFile = "/tmp/dbconnection.log";
/**
* Creates a new database connection
*
* @param $db_host
* @param $db_name
* @param $db_user
* @param $db_pass
* @param $memcache_host
* @param $memcache_port
*/
public function __construct($db_host = "localhost", $db_name = "", $db_user = "root", $db_pass = "", $memcache_host = "", $memcache_port = 11211)
{
$this->databaseHost = $db_host;
$this->databaseUser = $db_user;
$this->databasePass = $db_pass;
$this->databaseName = $db_name;
$this->memcacheHost = $memcache_host;
$this->memcachePort = $memcache_port;
}
public function __wakeup()
{
$this->connected = false;
$this->memcacheConnected = false;
}
public function isConnected()
{
return $this->connected;
}
public function getDateTimeString($date_string)
{
return date('Y/M/d h:m:s', strtotime($date_string));
}
/**
* Runs DB Query using mysql function
*
* Returns results as an array of objects.
* Optional param ('explicitType') is used to pass a class type to AMF
*
* @access private
*/
public function query($sql, $ignoreError = false, $explicitType = "")
{
$rs = $this->execute($sql, $ignoreError);
$results = array();
if (is_resource($rs)) {
while ($row = mysql_fetch_array($rs, MYSQL_ASSOC)) {
// convert ints and float to actual ints and floats
$col_n = 0;
foreach ($row as $col => $val) {
switch (mysql_field_type($rs, $col_n)) {
case 'int':
$row[$col] = (int)$val;
break;
case 'real':
$row[$col] = (float)$val;
break;
}
$col_n++;
}
$obj = (object)$row;
if ($explicitType) $obj->_explicitType = $explicitType;
$results[] = $obj;
}
}
//if(count($results)==1) return $results[0];
return $results;
}
/**
* Default cache time - 60 minutes (3600 seconds)
*/
public function queryCached($sql, $seconds = 3600, $explicitType = null)
{
if (!$this->memcacheConnected && $this->memcacheHost && $this->memcachePort) {
$this->connectMemcache();
}
$key = MD5($this->databaseHost . '_' . $this->databaseName . '_' . $this->databaseUser) . '_' . MD5($sql);
if ($this->memcacheConnected) {
$result = $this->memcache->get($key);
}
if (!$result) {
$result = $this->query($sql, false, $explicitType);
if ($this->memcacheConnected) {
$this->memcache->set($key, $result, MEMCACHE_COMPRESSED, $seconds);
}
}
return $result;
}
/**
* Shortcut to return first record
*
* @param $sql
* @param $ignoreError
* @param $explicitType
*/
public function getOne($sql, $ignoreError = false, $explicitType = "")
{
return @array_shift($this->query($sql, $ignoreError, $explicitType));
}
/**
* Execute a query and return mysql resource on success
*
* Throws an exception on errors unless ignoreError is true
*/
public function execute($sql, $ignoreError = false)
{
if (!$this->connected) $this->connect();
$this->trace("[DBConnection] execute: " . $sql);
$rs = mysql_query($sql);
if (!$rs) {
if ($ignoreError !== true) throw new Exception(mysql_error());
return false;
} else {
return $rs;
}
}
public function connect()
{
if ($this->connected) return;
$this->connected = @mysql_connect($this->databaseHost, $this->databaseUser, $this->databasePass) && @mysql_select_db($this->databaseName);
// try again in 1 second
if (!$this->connected) {
sleep(1);
$this->connected = @mysql_connect($this->databaseHost, $this->databaseUser, $this->databasePass) && @mysql_select_db($this->databaseName);
}
if (!$this->connected) {
$this->trace("[DBConnection] Failed to Connect");
throw new Exception("Unable to connect to the database {$this->databaseName} at {$this->databaseHost}");
}
}
/**
* Initialize memcache connection
*/
protected function connectMemcache()
{
$host = $this->memcacheHost;
$port = $this->memcachePort;
$this->memcacheConnected = false;
// init memcache
if (@class_exists('Memcache') && $host != null && $port != null) {
$this->memcache = new Memcache();
if (@$this->memcache->connect($host, $port)) {
$this->memcacheConnected = true;
} else if (@$this->memcache->connect($host, $port)) {
// try again to avoid intermittent connection issues
$this->memcacheConnected = true;
}
}
}
protected function trace($s)
{
if (!$this->debugLogEnabled) return;
if (!file_exists($this->debugLogFile)) {
touch($this->debugLogFile);
}
$fh = @fopen($this->debugLogFile, 'a');
if (is_resource($fh)) {
fwrite($fh, "$s\n");
fclose($fh);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment