Created
January 14, 2014 09:43
-
-
Save josegonzalez/8415777 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* APC-based WordPress Database Access Abstraction Object | |
* | |
* Extends the wpdb class in order to cache queries in APC | |
* | |
* Falls back to non-APC database when requesting an admin resource or | |
* the query modifies the database. | |
* | |
* Using something like Memcached might be better as we can namespace | |
* the keys and clear them whenever we need to without affecting other apps | |
* on the server | |
* | |
* @link http://codex.wordpress.org/Function_Reference/wpdb_Class | |
*/ | |
class APC_WPDB extends wpdb { | |
/** | |
* Perform a MySQL database query, using current database connection. | |
* | |
* More information can be found on the codex page. | |
* | |
* @since 0.71 | |
* | |
* @param string $query Database query | |
* @return int|false Number of rows affected/selected or false on error | |
*/ | |
function query( $query ) { | |
if ( ! $this->ready ) | |
return false; | |
// some queries are made before the plugins have been | |
// loaded, and thus cannot be filtered with this method | |
if ( function_exists( 'apply_filters' ) ) | |
$query = apply_filters( 'query', $query ); | |
$this->flush(); | |
// Log how the function was called | |
$this->func_call = "\$db->query(\"$query\")"; | |
// Keep track of the last query for debug.. | |
$this->last_query = $query; | |
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) | |
$this->timer_start(); | |
// Don't try caching any database altering queries | |
// Or WordPress's lovely SQL_CALC_FOUND_ROWS related-queries | |
// This is a performance hit, but wordpress appears to enjoy SQL_CALC_FOUND_ROWS | |
// And until they move away from it (never), these queries cannot be safely cached | |
// TODO: Cache SQL_CALC_FOUND_ROWS queries via request | |
if (preg_match( "/^\\s*(insert|delete|update|replace|alter|FOUND_ROWS) /i", $query) || preg_match("/FOUND_ROWS/i", $query)) { | |
return $this->no_cache_query($query); | |
} | |
$response = $this->getCache($query); | |
if ($response === false) { | |
return $this->no_cache_query($query); | |
} | |
// Cache the shit out of this bitch | |
$this->num_queries++; | |
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) | |
$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); | |
$this->col_info = $response['col_info']; | |
$this->last_result = $response['last_result']; | |
$this->num_rows = $response['num_rows']; | |
return $response['return']; | |
} | |
/** | |
* Performs a regular query against the | |
* database without caching the response | |
* | |
* @param string $query SQL Query being performed | |
* @return mixed result of query, or false on error | |
*/ | |
function no_cache_query($query) { | |
$this->result = @mysql_query( $query, $this->dbh ); | |
$this->num_queries++; | |
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) | |
$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); | |
// If there is an error then take note of it.. | |
if ( $this->last_error = mysql_error( $this->dbh ) ) { | |
$this->print_error(); | |
return false; | |
} | |
$return_val = 0; | |
if ( preg_match( '/^\s*(create|alter|truncate|drop) /i', $query ) ) { | |
$return_val = $this->result; | |
} elseif ( preg_match( '/^\s*(insert|delete|update|replace) /i', $query ) ) { | |
$this->rows_affected = mysql_affected_rows( $this->dbh ); | |
// Take note of the insert_id | |
if ( preg_match( "/^\s*(insert|replace) /i", $query ) ) { | |
$this->insert_id = mysql_insert_id($this->dbh); | |
} | |
// Return number of rows affected | |
$return_val = $this->rows_affected; | |
} else { | |
$i = 0; | |
while ( $i < @mysql_num_fields( $this->result ) ) { | |
$this->col_info[$i] = @mysql_fetch_field( $this->result ); | |
$i++; | |
} | |
$num_rows = 0; | |
while ( $row = @mysql_fetch_object( $this->result ) ) { | |
$this->last_result[$num_rows] = $row; | |
$num_rows++; | |
} | |
@mysql_free_result( $this->result ); | |
// Log number of rows the query returned | |
// and return number of rows selected | |
$this->num_rows = $num_rows; | |
$return_val = $num_rows; | |
$this->setCache($query, array( | |
'col_info' => $this->col_info, | |
'last_result' => $this->last_result, | |
'num_rows' => $this->num_rows, | |
'return' => $return_val, | |
)); | |
} | |
return $return_val; | |
} | |
/** | |
* Sets a cache value | |
* | |
* @param string $key name of unsha'd cache key | |
* @param mixed $value value to cache | |
* @param int $time time to cache in seconds | |
* @return boolean returns the success of the apc value caching | |
*/ | |
public function setCache($key, $value, $time = 300) { | |
if ($value === false) return false; | |
return apc_add(sha1($key), $value, $time); | |
} | |
/** | |
* Retrieves a key from cache | |
* | |
* @param string $key name of unsha'd cache key | |
* @return mixed cached resultset pertaining to the key | |
*/ | |
public function getCache($key) { | |
return apc_fetch(sha1($key)); | |
} | |
} | |
/** | |
* Convenience method that can be used to check if caching is possible | |
* | |
* @return boolean true is the current request is cacheable, false otherwise | |
*/ | |
function apc_canCacheQueries() { | |
if ((defined('WP_ADMIN') && WP_ADMIN) || (defined('DOING_CRON') && DOING_CRON) || (defined('DOING_AJAX') && DOING_AJAX)) { | |
return false; | |
} | |
if (preg_match('/(wp-admin|wp-login|wp-register|wp-signup)/', $_SERVER['REQUEST_URI']) || isset($_GET['preview'])) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Creates a WPDB Object which is APC-based when cacheable and WP-based when not | |
*/ | |
if (!isset($wpdb)) { | |
if (function_exists('apc_fetch') && apc_canCacheQueries()) { | |
$wpdb = new APC_WPDB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST ); | |
} else { | |
$wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment