Overview

Packages

  • Cache

Classes

  • Horde_Cache
  • Horde_Cache_Exception
  • Horde_Cache_Storage_Apc
  • Horde_Cache_Storage_Base
  • Horde_Cache_Storage_Eaccelerator
  • Horde_Cache_Storage_File
  • Horde_Cache_Storage_Memcache
  • Horde_Cache_Storage_Mock
  • Horde_Cache_Storage_Null
  • Horde_Cache_Storage_Session
  • Horde_Cache_Storage_Sql
  • Horde_Cache_Storage_Stack
  • Horde_Cache_Storage_Xcache
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This class provides cache storage in a SQL databsae.
  4:  *
  5:  * The table structure for the cache is as follows:
  6:  * <pre>
  7:  * CREATE TABLE horde_cache (
  8:  *     cache_id          VARCHAR(32) NOT NULL,
  9:  *     cache_timestamp   BIGINT NOT NULL,
 10:  *     cache_data        LONGBLOB,
 11:  *     (Or on PostgreSQL:)
 12:  *     cache_data        TEXT,
 13:  *     (Or on some other DBMS systems:)
 14:  *     cache_data        IMAGE,
 15:  *
 16:  *     PRIMARY KEY (cache_id)
 17:  * );
 18:  * </pre>
 19:  *
 20:  * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
 21:  *
 22:  * See the enclosed file COPYING for license information (LGPL). If you
 23:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 24:  *
 25:  * @author   Ben Klang <ben@alkaloid.net>
 26:  * @author   Michael Slusarz <slusarz@horde.org>
 27:  * @category Horde
 28:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 29:  * @package  Cache
 30:  */
 31: class Horde_Cache_Storage_Sql extends Horde_Cache_Storage_Base
 32: {
 33:     /**
 34:      * Handle for the current database connection.
 35:      *
 36:      * @var Horde_Db_Adapter
 37:      */
 38:     protected $_db;
 39: 
 40:     /**
 41:      * Constructor.
 42:      *
 43:      * @param array $params  Parameters:
 44:      * <pre>
 45:      * 'db' - (Horde_Db_Adapter) [REQUIRED] The DB instance.
 46:      * 'table' - (string) The name of the cache table.
 47:      *           DEFAULT: 'horde_cache'
 48:      * </pre>
 49:      *
 50:      * @throws Horde_Cache_Exception
 51:      */
 52:     public function __construct($params = array())
 53:     {
 54:         if (!isset($params['db'])) {
 55:             throw new Horde_Cache_Exception('Missing db parameter.');
 56:         }
 57:         $this->_db = $params['db'];
 58:         unset($params['db']);
 59: 
 60:         $params = array_merge(array(
 61:             'table' => 'horde_cache',
 62:         ), $params);
 63: 
 64:         parent::__construct($params);
 65:     }
 66: 
 67:     /**
 68:      * Destructor.
 69:      */
 70:     public function __destruct()
 71:     {
 72:         /* Only do garbage collection 0.1% of the time we create an object. */
 73:         if (rand(0, 999) != 0) {
 74:             return;
 75:         }
 76: 
 77:         $query = 'DELETE FROM ' . $this->_params['table'] .
 78:                  ' WHERE cache_expiration < ? AND cache_expiration <> 0';
 79:         $values = array(time());
 80: 
 81:         try {
 82:             $this->_db->delete($query, $values);
 83:         } catch (Horde_Db_Exception $e) {}
 84:     }
 85: 
 86:     /**
 87:      */
 88:     public function get($key, $lifetime = 0)
 89:     {
 90:         $okey = $key;
 91:         $key = hash('md5', $key);
 92: 
 93:         $timestamp = time();
 94:         $maxage = $timestamp - $lifetime;
 95: 
 96:         /* Build SQL query. */
 97:         $query = 'SELECT cache_data FROM ' . $this->_params['table'] .
 98:                  ' WHERE cache_id = ?';
 99:         $values = array($key);
100: 
101:         // 0 lifetime checks for objects which have no expiration
102:         if ($lifetime != 0) {
103:             $query .= ' AND cache_timestamp >= ?';
104:             $values[] = $maxage;
105:         }
106: 
107:         try {
108:             $result = $this->_db->selectValue($query, $values);
109:         } catch (Horde_Db_Exception $e) {
110:             return false;
111:         }
112: 
113:         if (!$result) {
114:             /* No rows were found - cache miss */
115:             if ($this->_logger) {
116:                 $this->_logger->log(sprintf('Cache miss: %s (Id %s newer than %d)', $okey, $key, $maxage), 'DEBUG');
117:             }
118:             return false;
119:         }
120: 
121:         if ($this->_logger) {
122:             $this->_logger->log(sprintf('Cache hit: %s (Id %s newer than %d)', $okey, $key, $maxage), 'DEBUG');
123:         }
124: 
125:         return $result;
126:     }
127: 
128:     /**
129:      */
130:     public function set($key, $data, $lifetime = 0)
131:     {
132:         $okey = $key;
133:         $key = hash('md5', $key);
134: 
135:         $timestamp = time();
136: 
137:         // 0 lifetime indicates the object should not be GC'd.
138:         $expiration = ($lifetime === 0)
139:             ? 0
140:             : ($lifetime + $timestamp);
141: 
142:         if ($this->_logger) {
143:             $this->_logger->log(sprintf('Cache set: %s (Id %s set at %d expires at %d)', $okey, $key, $timestamp, $expiration), 'DEBUG');
144:         }
145: 
146:         // Remove any old cache data and prevent duplicate keys
147:         $query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE cache_id=?';
148:         $values = array($key);
149:         try {
150:             $this->_db->delete($query, $values);
151:         } catch (Horde_Db_Exception $e) {}
152: 
153:         /* Build SQL query. */
154:         $query = 'INSERT INTO ' . $this->_params['table'] .
155:                  ' (cache_id, cache_timestamp, cache_expiration, cache_data)' .
156:                  ' VALUES (?, ?, ?, ?)';
157:         $values = array($key, $timestamp, $expiration, $data);
158: 
159:         try {
160:             $this->_db->insert($query, $values);
161:         } catch (Horde_Db_Exception $e) {
162:             throw new Horde_Cache_Exception($e);
163:         }
164:     }
165: 
166:     /**
167:      */
168:     public function exists($key, $lifetime = 0)
169:     {
170:         $okey = $key;
171:         $key = hash('md5', $key);
172: 
173:         /* Build SQL query. */
174:         $query = 'SELECT 1 FROM ' . $this->_params['table'] .
175:                  ' WHERE cache_id = ?';
176:         $values = array($key);
177: 
178:         // 0 lifetime checks for objects which have no expiration
179:         if ($lifetime != 0) {
180:             $query .= ' AND cache_timestamp >= ?';
181:             $values[] = time() - $lifetime;
182:         }
183: 
184:         try {
185:             $result = $this->_db->selectValue($query, $values);
186:         } catch (Horde_Db_Exception $e) {
187:             return false;
188:         }
189: 
190:         $timestamp = time();
191:         if (empty($result)) {
192:             if ($this->_logger) {
193:                 $this->_logger->log(sprintf('Cache exists() miss: %s (Id %s newer than %d)', $okey, $key, $timestamp), 'DEBUG');
194:             }
195:             return false;
196:         }
197: 
198:         if ($this->_logger) {
199:             $this->_logger->log(sprintf('Cache exists() hit: %s (Id %s newer than %d)', $okey, $key, $timestamp), 'DEBUG');
200:         }
201: 
202:         return true;
203:     }
204: 
205:     /**
206:      */
207:     public function expire($key)
208:     {
209:         $key = hash('md5', $key);
210: 
211:         $query = 'DELETE FROM ' . $this->_params['table'] .
212:                  ' WHERE cache_id = ?';
213:         $values = array($key);
214: 
215:         try {
216:             $this->_db->delete($query, $values);
217:         } catch (Horde_Db_Exception $e) {
218:             return false;
219:         }
220: 
221:         return true;
222:     }
223: 
224:     /**
225:      */
226:     public function clear()
227:     {
228:         $query = 'DELETE FROM ' . $this->_params['table'];
229: 
230:         try {
231:             $this->_db->delete($query);
232:         } catch (Horde_Db_Exception $e) {
233:             throw new Horde_Cache_Exception($e);
234:         }
235:     }
236: 
237: }
238: 
API documentation generated by ApiGen