Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • DevNullStorage
  • FileStorage
  • MemcachedStorage
  • MemoryStorage
  • NewMemcachedStorage
  • SQLiteJournal
  • SQLiteStorage

Interfaces

  • IJournal
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Caching\Storages;
  9: 
 10: use Nette;
 11: use Nette\Caching\Cache;
 12: 
 13: 
 14: /**
 15:  * Memcached storage using memcached extension.
 16:  */
 17: class NewMemcachedStorage implements Nette\Caching\IStorage, Nette\Caching\IBulkReader
 18: {
 19:     use Nette\SmartObject;
 20: 
 21:     /** @internal cache structure */
 22:     const META_CALLBACKS = 'callbacks',
 23:         META_DATA = 'data',
 24:         META_DELTA = 'delta';
 25: 
 26:     /** @var \Memcached */
 27:     private $memcached;
 28: 
 29:     /** @var string */
 30:     private $prefix;
 31: 
 32:     /** @var IJournal */
 33:     private $journal;
 34: 
 35: 
 36:     /**
 37:      * Checks if Memcached extension is available.
 38:      * @return bool
 39:      */
 40:     public static function isAvailable()
 41:     {
 42:         return extension_loaded('memcached');
 43:     }
 44: 
 45: 
 46:     public function __construct($host = 'localhost', $port = 11211, $prefix = '', IJournal $journal = null)
 47:     {
 48:         if (!static::isAvailable()) {
 49:             throw new Nette\NotSupportedException("PHP extension 'memcached' is not loaded.");
 50:         }
 51: 
 52:         $this->prefix = $prefix;
 53:         $this->journal = $journal;
 54:         $this->memcached = new \Memcached;
 55:         if ($host) {
 56:             $this->addServer($host, $port);
 57:         }
 58:     }
 59: 
 60: 
 61:     public function addServer($host = 'localhost', $port = 11211)
 62:     {
 63:         if ($this->memcached->addServer($host, $port, 1) === false) {
 64:             $error = error_get_last();
 65:             throw new Nette\InvalidStateException("Memcached::addServer(): $error[message].");
 66:         }
 67:     }
 68: 
 69: 
 70:     /**
 71:      * @return \Memcached
 72:      */
 73:     public function getConnection()
 74:     {
 75:         return $this->memcached;
 76:     }
 77: 
 78: 
 79:     /**
 80:      * Read from cache.
 81:      * @param  string
 82:      * @return mixed
 83:      */
 84:     public function read($key)
 85:     {
 86:         $key = urlencode($this->prefix . $key);
 87:         $meta = $this->memcached->get($key);
 88:         if (!$meta) {
 89:             return null;
 90:         }
 91: 
 92:         // meta structure:
 93:         // array(
 94:         //     data => stored data
 95:         //     delta => relative (sliding) expiration
 96:         //     callbacks => array of callbacks (function, args)
 97:         // )
 98: 
 99:         // verify dependencies
100:         if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
101:             $this->memcached->delete($key, 0);
102:             return null;
103:         }
104: 
105:         if (!empty($meta[self::META_DELTA])) {
106:             $this->memcached->replace($key, $meta, $meta[self::META_DELTA] + time());
107:         }
108: 
109:         return $meta[self::META_DATA];
110:     }
111: 
112: 
113:     /**
114:      * Reads from cache in bulk.
115:      * @param  string
116:      * @return array key => value pairs, missing items are omitted
117:      */
118:     public function bulkRead(array $keys)
119:     {
120:         $prefixedKeys = array_map(function ($key) {
121:             return urlencode($this->prefix . $key);
122:         }, $keys);
123:         $keys = array_combine($prefixedKeys, $keys);
124:         $metas = $this->memcached->getMulti($prefixedKeys);
125:         $result = [];
126:         $deleteKeys = [];
127:         foreach ($metas as $prefixedKey => $meta) {
128:             if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
129:                 $deleteKeys[] = $prefixedKey;
130:             } else {
131:                 $result[$keys[$prefixedKey]] = $meta[self::META_DATA];
132:             }
133: 
134:             if (!empty($meta[self::META_DELTA])) {
135:                 $this->memcached->replace($prefixedKey, $meta, $meta[self::META_DELTA] + time());
136:             }
137:         }
138:         if (!empty($deleteKeys)) {
139:             $this->memcached->deleteMulti($deleteKeys, 0);
140:         }
141: 
142:         return $result;
143:     }
144: 
145: 
146:     /**
147:      * Prevents item reading and writing. Lock is released by write() or remove().
148:      * @param  string
149:      * @return void
150:      */
151:     public function lock($key)
152:     {
153:     }
154: 
155: 
156:     /**
157:      * Writes item into the cache.
158:      * @param  string
159:      * @param  mixed
160:      * @return void
161:      */
162:     public function write($key, $data, array $dp)
163:     {
164:         if (isset($dp[Cache::ITEMS])) {
165:             throw new Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.');
166:         }
167: 
168:         $key = urlencode($this->prefix . $key);
169:         $meta = [
170:             self::META_DATA => $data,
171:         ];
172: 
173:         $expire = 0;
174:         if (isset($dp[Cache::EXPIRATION])) {
175:             $expire = (int) $dp[Cache::EXPIRATION];
176:             if (!empty($dp[Cache::SLIDING])) {
177:                 $meta[self::META_DELTA] = $expire; // sliding time
178:             }
179:         }
180: 
181:         if (isset($dp[Cache::CALLBACKS])) {
182:             $meta[self::META_CALLBACKS] = $dp[Cache::CALLBACKS];
183:         }
184: 
185:         if (isset($dp[Cache::TAGS]) || isset($dp[Cache::PRIORITY])) {
186:             if (!$this->journal) {
187:                 throw new Nette\InvalidStateException('CacheJournal has not been provided.');
188:             }
189:             $this->journal->write($key, $dp);
190:         }
191: 
192:         $this->memcached->set($key, $meta, $expire);
193:     }
194: 
195: 
196:     /**
197:      * Removes item from the cache.
198:      * @param  string
199:      * @return void
200:      */
201:     public function remove($key)
202:     {
203:         $this->memcached->delete(urlencode($this->prefix . $key), 0);
204:     }
205: 
206: 
207:     /**
208:      * Removes items from the cache by conditions & garbage collector.
209:      * @param  array  conditions
210:      * @return void
211:      */
212:     public function clean(array $conditions)
213:     {
214:         if (!empty($conditions[Cache::ALL])) {
215:             $this->memcached->flush();
216: 
217:         } elseif ($this->journal) {
218:             foreach ($this->journal->clean($conditions) as $entry) {
219:                 $this->memcached->delete($entry, 0);
220:             }
221:         }
222:     }
223: }
224: 
Nette 2.4-20170829 API API documentation generated by ApiGen 2.8.0