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
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

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

Interfaces

  • IJournal
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  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
 23:         META_CALLBACKS = 'callbacks',
 24:         META_DATA = 'data',
 25:         META_DELTA = 'delta';
 26: 
 27:     /** @var \Memcached */
 28:     private $memcached;
 29: 
 30:     /** @var string */
 31:     private $prefix;
 32: 
 33:     /** @var IJournal */
 34:     private $journal;
 35: 
 36: 
 37:     /**
 38:      * Checks if Memcached extension is available.
 39:      * @return bool
 40:      */
 41:     public static function isAvailable()
 42:     {
 43:         return extension_loaded('memcached');
 44:     }
 45: 
 46: 
 47:     public function __construct($host = 'localhost', $port = 11211, $prefix = '', IJournal $journal = null)
 48:     {
 49:         if (!static::isAvailable()) {
 50:             throw new Nette\NotSupportedException("PHP extension 'memcached' is not loaded.");
 51:         }
 52: 
 53:         $this->prefix = $prefix;
 54:         $this->journal = $journal;
 55:         $this->memcached = new \Memcached;
 56:         if ($host) {
 57:             $this->addServer($host, $port);
 58:         }
 59:     }
 60: 
 61: 
 62:     public function addServer($host = 'localhost', $port = 11211)
 63:     {
 64:         if ($this->memcached->addServer($host, $port, 1) === false) {
 65:             $error = error_get_last();
 66:             throw new Nette\InvalidStateException("Memcached::addServer(): $error[message].");
 67:         }
 68:     }
 69: 
 70: 
 71:     /**
 72:      * @return \Memcached
 73:      */
 74:     public function getConnection()
 75:     {
 76:         return $this->memcached;
 77:     }
 78: 
 79: 
 80:     public function read($key)
 81:     {
 82:         $key = urlencode($this->prefix . $key);
 83:         $meta = $this->memcached->get($key);
 84:         if (!$meta) {
 85:             return null;
 86:         }
 87: 
 88:         // meta structure:
 89:         // array(
 90:         //     data => stored data
 91:         //     delta => relative (sliding) expiration
 92:         //     callbacks => array of callbacks (function, args)
 93:         // )
 94: 
 95:         // verify dependencies
 96:         if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
 97:             $this->memcached->delete($key, 0);
 98:             return null;
 99:         }
100: 
101:         if (!empty($meta[self::META_DELTA])) {
102:             $this->memcached->replace($key, $meta, $meta[self::META_DELTA] + time());
103:         }
104: 
105:         return $meta[self::META_DATA];
106:     }
107: 
108: 
109:     public function bulkRead(array $keys)
110:     {
111:         $prefixedKeys = array_map(function ($key) {
112:             return urlencode($this->prefix . $key);
113:         }, $keys);
114:         $keys = array_combine($prefixedKeys, $keys);
115:         $metas = $this->memcached->getMulti($prefixedKeys);
116:         $result = [];
117:         $deleteKeys = [];
118:         foreach ($metas as $prefixedKey => $meta) {
119:             if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
120:                 $deleteKeys[] = $prefixedKey;
121:             } else {
122:                 $result[$keys[$prefixedKey]] = $meta[self::META_DATA];
123:             }
124: 
125:             if (!empty($meta[self::META_DELTA])) {
126:                 $this->memcached->replace($prefixedKey, $meta, $meta[self::META_DELTA] + time());
127:             }
128:         }
129:         if (!empty($deleteKeys)) {
130:             $this->memcached->deleteMulti($deleteKeys, 0);
131:         }
132: 
133:         return $result;
134:     }
135: 
136: 
137:     public function lock($key)
138:     {
139:     }
140: 
141: 
142:     public function write($key, $data, array $dp)
143:     {
144:         if (isset($dp[Cache::ITEMS])) {
145:             throw new Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.');
146:         }
147: 
148:         $key = urlencode($this->prefix . $key);
149:         $meta = [
150:             self::META_DATA => $data,
151:         ];
152: 
153:         $expire = 0;
154:         if (isset($dp[Cache::EXPIRATION])) {
155:             $expire = (int) $dp[Cache::EXPIRATION];
156:             if (!empty($dp[Cache::SLIDING])) {
157:                 $meta[self::META_DELTA] = $expire; // sliding time
158:             }
159:         }
160: 
161:         if (isset($dp[Cache::CALLBACKS])) {
162:             $meta[self::META_CALLBACKS] = $dp[Cache::CALLBACKS];
163:         }
164: 
165:         if (isset($dp[Cache::TAGS]) || isset($dp[Cache::PRIORITY])) {
166:             if (!$this->journal) {
167:                 throw new Nette\InvalidStateException('CacheJournal has not been provided.');
168:             }
169:             $this->journal->write($key, $dp);
170:         }
171: 
172:         $this->memcached->set($key, $meta, $expire);
173:     }
174: 
175: 
176:     public function remove($key)
177:     {
178:         $this->memcached->delete(urlencode($this->prefix . $key), 0);
179:     }
180: 
181: 
182:     public function clean(array $conditions)
183:     {
184:         if (!empty($conditions[Cache::ALL])) {
185:             $this->memcached->flush();
186: 
187:         } elseif ($this->journal) {
188:             foreach ($this->journal->clean($conditions) as $entry) {
189:                 $this->memcached->delete($entry, 0);
190:             }
191:         }
192:     }
193: }
194: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0