├── .gitignore ├── Extended └── Cache │ └── Backend │ └── Redis.php ├── LICENSE ├── README.markdown └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /Extended/Cache/Backend/Redis.php: -------------------------------------------------------------------------------- 1 | 43 | */ 44 | 45 | /** 46 | * @see Zend_Cache_Backend_Interface 47 | */ 48 | require_once 'Zend/Cache/Backend/ExtendedInterface.php'; 49 | 50 | /** 51 | * @see Zend_Cache_Backend 52 | */ 53 | require_once 'Zend/Cache/Backend.php'; 54 | 55 | class Extended_Cache_Backend_Redis extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface 56 | { 57 | /** 58 | * Default Values 59 | */ 60 | const DEFAULT_HOST = '127.0.0.1'; 61 | const DEFAULT_PORT = 6379; 62 | const DEFAULT_PERSISTENT = true; 63 | const DEFAULT_DBINDEX = 0; 64 | const DEFAULT_AUTH = false; 65 | const DEFAULT_AUTH_PASSWORD = null; 66 | 67 | protected $_options = array( 68 | 'servers' => array( 69 | array( 70 | 'host' => self::DEFAULT_HOST, 71 | 'port' => self::DEFAULT_PORT, 72 | 'persistent' => self::DEFAULT_PERSISTENT, 73 | 'dbindex' => self::DEFAULT_DBINDEX, 74 | 'auth' => self::DEFAULT_AUTH, 75 | 'password' => self::DEFAULT_AUTH_PASSWORD, 76 | ), 77 | ), 78 | 'key_prefix' => '', 79 | ); 80 | 81 | /** 82 | * @var Redis|null Redis object 83 | */ 84 | protected $_redis = null; 85 | 86 | /** 87 | * Constructor 88 | * 89 | * @param array $options associative array of options 90 | * @throws Zend_Cache_Exception 91 | * @return void 92 | */ 93 | public function __construct(array $options = array()) 94 | { 95 | if (!extension_loaded('redis')) { 96 | Zend_Cache::throwException('The redis extension must be loaded for using this backend !'); 97 | } 98 | parent::__construct($options); 99 | $this->_redis = new Redis; 100 | 101 | foreach ($this->_options['servers'] as $server) { 102 | if (!array_key_exists('port', $server)) { 103 | $server['port'] = self::DEFAULT_PORT; 104 | } 105 | if (!array_key_exists('host', $server)) { 106 | $server['host'] = self::DEFAULT_HOST; 107 | } 108 | if (!array_key_exists('persistent', $server)) { 109 | $server['persistent'] = self::DEFAULT_PERSISTENT; 110 | } 111 | if (!array_key_exists('dbindex', $server)) { 112 | $server['dbindex'] = self::DEFAULT_DBINDEX; 113 | } 114 | if ($server['persistent']) { 115 | $result = $this->_redis->pconnect($server['host'], $server['port']); 116 | } else { 117 | $result = $this->_redis->connect($server['host'], $server['port']); 118 | } 119 | 120 | if ($this->_redis && array_key_exists('auth', $server) && $server['auth']) { 121 | $this->_redis->auth($server['password']); 122 | } 123 | 124 | if ($result) 125 | $this->_redis->select($server['dbindex']); 126 | else 127 | $this->_redis = null; 128 | } 129 | } 130 | 131 | /** 132 | * Returns status on if cache backend is connected to Redis 133 | * 134 | * @return bool true if cache backend is connected to Redis server. 135 | */ 136 | public function isConnected() 137 | { 138 | if ($this->_redis) 139 | return true; 140 | return false; 141 | } 142 | 143 | 144 | /** 145 | * Test if a cache is available for the given id and (if yes) return it (false else) 146 | * 147 | * @param string $id cache id 148 | * @param boolean $doNotTestCacheValidity Redis GET always acts as if $doNotTestCacheValidity is true. 149 | * @return string|false cached datas 150 | */ 151 | public function load($id, $doNotTestCacheValidity = true) 152 | { 153 | return $this->_load($id); 154 | } 155 | 156 | /** 157 | * Test if a cache is available or not (for the given id) 158 | * 159 | * @param string $id cache id 160 | * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record 161 | */ 162 | public function test($id) 163 | { 164 | return $this->_test($id, false); 165 | } 166 | 167 | /** 168 | * Save some string datas into a cache record 169 | * 170 | * Note : $data is always "string" (serialization is done by the 171 | * core not by the backend) 172 | * 173 | * @param string $data Datas to cache 174 | * @param string $id Cache id 175 | * @param mixed $tags Array of strings, the cache record will be tagged by each string entry, if false, key 176 | * can only be read if $doNotTestCacheValidity is true 177 | * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) 178 | * @return boolean true if no problem 179 | */ 180 | public function save($data, $id, $tags = array(), $specificLifetime = false) 181 | { 182 | if (!$this->_redis) 183 | return false; 184 | 185 | if (is_string($tags)) 186 | $tags = array($tags); 187 | 188 | $lifetime = $this->getLifetime($specificLifetime); 189 | $keyFromItemTags = $this->_keyFromItemTags($id); 190 | $keyFromId = $this->_keyFromId($id); 191 | 192 | // If no tags were provided, just set the value and return as quickly as possible 193 | if (empty($tags)) { 194 | $this->_redis->delete($keyFromItemTags); // Wipe out any existing tags for this id 195 | if ($lifetime === null) { 196 | $return = $this->_redis->set($keyFromId, $data); 197 | } else { 198 | $return = $this->_redis->setex($keyFromId, $lifetime, $data); 199 | } 200 | return $return; 201 | } 202 | 203 | // Before we enter "multi" mode, grab a list of tag TTLs. 204 | // Simulating behavior of redis 2.8 (-1 for no expiration, -2 for nonexistent key) 205 | $tagTTLs = array(); 206 | foreach ($tags as $tag) { 207 | if (empty($tag)) 208 | continue; 209 | 210 | $keyFromTag = $this->_keyFromTag($tag); 211 | 212 | $ttl = $this->_redis->ttl($keyFromTag); 213 | if ($ttl == -1 && !$this->_redis->exists($keyFromTag)) 214 | $ttl = -2; 215 | $tagTTLs[$tag] = $ttl; 216 | } 217 | 218 | // Enter "multi" mode 219 | $this->_redis->multi(); 220 | 221 | if ($lifetime === null) { 222 | $this->_redis->set($keyFromId, $data); 223 | } else { 224 | $this->_redis->setex($keyFromId, $lifetime, $data); 225 | } 226 | 227 | $itemTags = array($keyFromItemTags); 228 | foreach ($tags as $tag) { 229 | if (empty($tag)) 230 | continue; 231 | 232 | $keyFromTag = $this->_keyFromTag($tag); 233 | 234 | // Keep track of the tags we will add to this item's list 235 | $itemTags[] = $tag; 236 | 237 | // Add this id to the tag's list of entries 238 | $this->_redis->sAdd($keyFromTag, $id); 239 | 240 | // For keys not already set to no expiration, make sure the TTL is correct 241 | $ttl = $tagTTLs[$tag]; 242 | if ($ttl != -1) { 243 | if ($lifetime === null && $ttl < 0) { 244 | $this->_redis->persist($keyFromTag); 245 | } elseif ($lifetime !== null && $ttl < $lifetime) { 246 | $this->_redis->setTimeout($keyFromTag, $lifetime); 247 | } 248 | } 249 | 250 | } 251 | 252 | $this->_redis->delete($keyFromItemTags); 253 | if (count($itemTags) > 1) { 254 | call_user_func_array(array($this->_redis, 'sAdd'), $itemTags); 255 | } 256 | 257 | if ($lifetime !== null) { 258 | $this->_redis->setTimeout($keyFromItemTags, $lifetime); 259 | } else { 260 | $this->_redis->persist($keyFromItemTags); 261 | } 262 | 263 | $return = $this->_redis->exec(); 264 | 265 | // If return is empty or contains any individual failures, return false 266 | return count($return) ? !in_array(false, $return, /* strict */ true) : false; 267 | } 268 | 269 | /** 270 | * Save some string datas into a cache record. Only the specific key will be stored and no tags. 271 | * Can only be read by load() if $doNotTestCacheValidity is true 272 | * 273 | * Note : $data is always "string" (serialization is done by the 274 | * core not by the backend) 275 | * 276 | * @param string $data Datas to cache 277 | * @param string $id Cache id 278 | * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) 279 | * @return boolean true if no problem 280 | */ 281 | protected function _storeKey($data, $id, $specificLifetime = false) 282 | { 283 | if (!$this->_redis) 284 | return false; 285 | 286 | $lifetime = $this->getLifetime($specificLifetime); 287 | 288 | if ($lifetime === null) { 289 | return $this->_redis->set($this->_keyFromId($id), $data); 290 | } else { 291 | return $this->_redis->setex($this->_keyFromId($id), $lifetime, $data); 292 | } 293 | } 294 | 295 | /** 296 | * Prefixes key ID 297 | * 298 | * @param string $id cache key 299 | * @return string prefixed id 300 | */ 301 | protected function _keyFromId($id) 302 | { 303 | return $this->_options['key_prefix'] . 'item__' . $id; 304 | } 305 | 306 | /** 307 | * Prefixes tag ID 308 | * 309 | * @param string $id tag key 310 | * @return string prefixed tag 311 | */ 312 | protected function _keyFromTag($id) 313 | { 314 | return $this->_options['key_prefix'] . 'tag__' . $id; 315 | } 316 | 317 | /** 318 | * Prefixes item tag ID 319 | * 320 | * @param string $id item tag key 321 | * @return string prefixed item tag 322 | */ 323 | protected function _keyFromItemTags($id) 324 | { 325 | return $this->_options['key_prefix'] . 'item_tags__' . $id; 326 | } 327 | 328 | /** 329 | * Remove a cache record 330 | * 331 | * @param string $id cache id 332 | * @return boolean true if no problem 333 | */ 334 | public function remove($id) 335 | { 336 | if (!$this->_redis) 337 | return false; 338 | 339 | if (!$id) 340 | return false; 341 | if (is_string($id)) 342 | $id = array($id); 343 | if (!count($id)) 344 | return false; 345 | $deleteIds = array(); 346 | foreach ($id as $i) { 347 | $deleteIds[] = $this->_keyFromItemTags($i); 348 | $deleteIds[] = $this->_keyFromId($i); 349 | } 350 | $this->_redis->delete($deleteIds); 351 | 352 | return true; 353 | } 354 | 355 | 356 | /** 357 | * Remove a cache tag record 358 | * 359 | * @param string $tag cache tag 360 | * @return boolean true if no problem 361 | */ 362 | public function removeTag($tag) 363 | { 364 | if (!$this->_redis) 365 | return false; 366 | 367 | if (is_string($tag)) 368 | $tag = array($tag); 369 | if (empty($tag)) 370 | return false; 371 | 372 | $deleteTags = array(); 373 | foreach ($tag as $t) { 374 | $deleteTags[] = $this->_keyFromTag($t); 375 | } 376 | if ($deleteTags && count($deleteTags)) 377 | $this->_redis->delete($deleteTags); 378 | 379 | return true; 380 | } 381 | 382 | /** 383 | * Returns wether a specific member key exists in the Redis set 384 | * 385 | * @param string $member 386 | * @param string $set 387 | * @return bool true or false 388 | */ 389 | public function existsInSet($member, $set) 390 | { 391 | if (!$this->_redis) 392 | return null; 393 | 394 | if (!$this->_redis->sIsMember($this->_keyFromId($set), $member)) 395 | return false; 396 | return true; 397 | } 398 | 399 | /** 400 | * Adds a key to a set 401 | * 402 | * @param mixed $member key(s) to add 403 | * @param string $set 404 | * @param string $specificLifetime lifetime, null for persistant 405 | * @return bool result of the add 406 | */ 407 | public function addToSet($member, $set, $specificLifetime = false) 408 | { 409 | if (!$this->_redis) 410 | return null; 411 | 412 | $lifetime = $this->getLifetime($specificLifetime); 413 | 414 | if (is_array($member)) { 415 | $redis = $this->_redis; 416 | $return = call_user_func_array(array($redis, 'sAdd'), array_merge(array($this->_keyFromId($set)), $member)); 417 | } else { 418 | $return = $this->_redis->sAdd($this->_keyFromId($set), $member); 419 | } 420 | if ($lifetime !== null) 421 | $this->_redis->setTimeout($this->_keyFromId($set), $lifetime); 422 | 423 | return $return; 424 | } 425 | 426 | /** 427 | * Removes a key from a redis set. 428 | * 429 | * @param mixed $member key(s) to remove 430 | * @param string $set 431 | * @return bool result of removal 432 | */ 433 | public function removeFromSet($member, $set) 434 | { 435 | if (!$this->_redis) 436 | return null; 437 | 438 | if (is_array($member)) { 439 | if (!count($member)) 440 | return true; 441 | $redis = $this->_redis; 442 | $return = call_user_func_array(array($redis, 'sRem'), array_merge(array($this->_keyFromId($set)), $member)); 443 | } else { 444 | $return = $this->_redis->sRem($this->_keyFromId($set), $member); 445 | } 446 | return $return; 447 | } 448 | 449 | /** 450 | * Returns all keys in a Redis set 451 | * 452 | * @param string $set 453 | * @return array member keys of set 454 | */ 455 | public function membersInSet($set) 456 | { 457 | if (!$this->_redis) 458 | return null; 459 | 460 | return $this->_redis->sMembers($this->_keyFromId($set)); 461 | } 462 | 463 | /** 464 | * Clean some cache records 465 | * 466 | * Available modes are : 467 | * 468 | * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) 469 | * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) 470 | * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags 471 | * ($tags can be an array of strings or a single string) 472 | * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} 473 | * ($tags can be an array of strings or a single string) 474 | * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags 475 | * ($tags can be an array of strings or a single string) 476 | * 477 | * @param string $mode clean mode 478 | * @param tags array $tags array of tags 479 | * @return boolean true if no problem 480 | */ 481 | public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) 482 | { 483 | return $this->_clean($mode, $tags); 484 | } 485 | 486 | /** 487 | * Clean some cache records (protected method used for recursive stuff) 488 | * 489 | * Available modes are : 490 | * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used) 491 | * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used) 492 | * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags 493 | * ($tags can be an array of strings or a single string) 494 | * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags} 495 | * ($tags can be an array of strings or a single string) 496 | * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags 497 | * ($tags can be an array of strings or a single string) 498 | * 499 | * @param string $dir Directory to clean 500 | * @param string $mode Clean mode 501 | * @param array $tags Array of tags 502 | * @throws Zend_Cache_Exception 503 | * @return boolean True if no problem 504 | */ 505 | protected function _clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) 506 | { 507 | if (!$this->_redis) 508 | return false; 509 | 510 | if ($mode == Zend_Cache::CLEANING_MODE_ALL) 511 | return $this->_redis->flushDb(); 512 | 513 | if ($mode == Zend_Cache::CLEANING_MODE_OLD) 514 | return true; /* Redis takes care of expire */ 515 | 516 | if ($mode == Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG && $tags && (is_string($tags) || count($tags))) { 517 | if (is_string($tags)) 518 | $tags = [$tags]; 519 | $idsToRemove = []; 520 | foreach ($tags as $tag) { 521 | $idsToRemove = array_merge($idsToRemove, $this->getIdsMatchingTags($tag)); 522 | } 523 | return $this->remove($idsToRemove); 524 | } 525 | 526 | if ($mode == Zend_Cache::CLEANING_MODE_MATCHING_TAG && $tags && (is_string($tags) || count($tags))) { 527 | return $this->remove($this->getIdsMatchingTags($tags)); 528 | } 529 | 530 | if ($mode == Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG) 531 | Zend_Cache::throwException('CLEANING_MODE_NOT_MATCHING_TAG not implemented for Redis cache'); 532 | 533 | Zend_Cache::throwException('Invalid mode for clean() method'); 534 | } 535 | 536 | /** 537 | * Test if the given cache id is available (and still valid as a cache record) 538 | * 539 | * @param string $id Cache id 540 | * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested 541 | * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record 542 | */ 543 | protected function _test($id, $doNotTestCacheValidity) 544 | { 545 | if (!$this->_redis) 546 | return false; 547 | 548 | if ($doNotTestCacheValidity) { 549 | return true; 550 | } 551 | $tags = $this->_redis->sMembers($this->_keyFromItemTags($id)); 552 | if (!$tags || !count($tags)) 553 | return false; 554 | foreach ($tags as $tag) { 555 | if ($tag && !$this->_redis->sIsMember($this->_keyFromTag($tag), $id)) 556 | return false; 557 | } 558 | 559 | return true; 560 | } 561 | 562 | /** 563 | * Return cached id 564 | * 565 | * @param string $id cache id 566 | * @return string|bool cached data, or FALSE if cache has no value for $id 567 | */ 568 | protected function _load($id) 569 | { 570 | if (!$this->_redis) 571 | return false; 572 | 573 | return $this->_redis->get($this->_keyFromId($id)); 574 | } 575 | 576 | /** 577 | * Return an array of stored cache ids. Not implemented for Redis cache 578 | * 579 | * @throws Zend_Cache_Exception 580 | */ 581 | public function getIds() 582 | { 583 | Zend_Cache::throwException('Not possible to get available IDs on Redis cache'); 584 | } 585 | 586 | 587 | /** 588 | * Return an array of stored tags. Not implemented for Redis cache 589 | * 590 | * @throws Zend_Cache_Exception 591 | */ 592 | public function getTags() 593 | { 594 | Zend_Cache::throwException('Not possible to get available tags on Redis cache'); 595 | } 596 | 597 | /** 598 | * Return an array of stored cache ids which match given tags 599 | * 600 | * In case of multiple tags, a logical AND is made between tags 601 | * 602 | * @param array $tags array of tags 603 | * @return array array of matching cache ids (string) 604 | */ 605 | public function getIdsMatchingTags($tags = array()) 606 | { 607 | if (!$this->_redis) 608 | return array(); 609 | 610 | if (!$tags) 611 | return array(); 612 | if ($tags && is_string($tags)) 613 | $tags = array($tags); 614 | 615 | $matchTags = array(); 616 | foreach ($tags as $tag) { 617 | $matchTags[] = $this->_keyFromTag($tag); 618 | } 619 | if (count($matchTags) == 1) 620 | return $this->_redis->sMembers($matchTags[0]); 621 | 622 | return $this->_redis->sInter($matchTags); 623 | } 624 | 625 | /** 626 | * Return an array of stored cache ids which don't match given tags. Not implemented for Redis cache 627 | * 628 | * In case of multiple tags, a logical OR is made between tags 629 | * 630 | * @param array $tags array of tags 631 | * @throws Zend_Cache_Exception 632 | */ 633 | public function getIdsNotMatchingTags($tags = array()) 634 | { 635 | Zend_Cache::throwException('Not possible to get IDs not matching tags on Redis cache'); 636 | } 637 | 638 | /** 639 | * Return an array of stored cache ids which match any given tags 640 | * 641 | * In case of multiple tags, a logical AND is made between tags 642 | * 643 | * @param array $tags array of tags 644 | * @return array array of any matching cache ids (string) 645 | */ 646 | public function getIdsMatchingAnyTags($tags = array()) 647 | { 648 | if (!$this->_redis) 649 | return array(); 650 | 651 | if (!$tags) 652 | return array(); 653 | if ($tags && is_string($tags)) 654 | $tags = array($tags); 655 | 656 | $return = array(); 657 | foreach ($tags as $tag) { 658 | foreach ($this->_redis->sMembers($this->_keyFromTag($tag)) as $id) { 659 | $return[] = $id; 660 | } 661 | } 662 | return $return; 663 | } 664 | 665 | /** 666 | * Return the filling percentage of the backend storage. Not implemented on Redis cache 667 | * 668 | * @throws Zend_Cache_Exception 669 | */ 670 | public function getFillingPercentage() 671 | { 672 | Zend_Cache::throwException('getFillingPercentage not implemented on Redis cache'); 673 | } 674 | 675 | /** 676 | * Return an array of metadatas for the given cache id. Not implemented on Redis cache 677 | * 678 | * @param string $id cache id 679 | * @throws Zend_Cache_Exception 680 | */ 681 | public function getMetadatas($id) 682 | { 683 | Zend_Cache::throwException('Metadata not implemented on Redis cache'); 684 | } 685 | 686 | /** 687 | * Give (if possible) an extra lifetime to the given cache id 688 | * 689 | * @param string $id cache id 690 | * @param int $extraLifetime 691 | * @return boolean true if ok 692 | */ 693 | public function touch($id, $extraLifetime) 694 | { 695 | if (!$this->_redis) 696 | return false; 697 | 698 | $tags = $this->_redis->sMembers($this->_keyFromItemTags($id)); 699 | 700 | $lifetime = $this->getLifetime($extraLifetime); 701 | $return = false; 702 | if ($lifetime !== null) { 703 | $this->_redis->setTimeout($this->_keyFromItemTags($id), $lifetime); 704 | $return = $this->_redis->setTimeout($this->_keyFromId($id), $lifetime); 705 | } else { 706 | $this->_redis->persist($this->_keyFromItemTags($id)); 707 | $return = $this->_redis->persist($this->_keyFromId($id)); 708 | } 709 | 710 | if ($tags) { 711 | foreach ($tags as $tag) { 712 | if ($tag) { 713 | $ttl = $this->_redis->ttl($this->_keyFromTag($tag)); 714 | if ($ttl !== false && $ttl !== -1 && $ttl < $lifetime && $lifetime !== null) 715 | $this->_redis->setTimeout($this->_keyFromTag($tag), $lifetime); 716 | else if ($ttl !== false && $ttl !== -1 && $lifetime === null) 717 | $this->_redis->persist($this->_keyFromTag($tag)); 718 | } 719 | } 720 | } 721 | 722 | return $return; 723 | } 724 | 725 | /** 726 | * Give (if possible) an extra lifetime to the given cache id (and only that key, no tags are updated) 727 | * 728 | * @param string $id cache id 729 | * @param int $extraLifetime 730 | * @return boolean true if ok 731 | */ 732 | protected function _touchKey($id, $extraLifetime) 733 | { 734 | if (!$this->_redis) 735 | return false; 736 | 737 | $data = $this->load($id, true); 738 | if ($data === false) 739 | return false; 740 | return $this->storeKey($data, $id, $extraLifetime); 741 | } 742 | 743 | /** 744 | * Return an associative array of capabilities (booleans) of the backend 745 | * 746 | * The array must include these keys : 747 | * - automatic_cleaning (is automating cleaning necessary) 748 | * - tags (are tags supported) 749 | * - expired_read (is it possible to read expired cache records 750 | * (for doNotTestCacheValidity option for example)) 751 | * - priority does the backend deal with priority when saving 752 | * - infinite_lifetime (is infinite lifetime can work with this backend) 753 | * - get_list (is it possible to get the list of cache ids and the complete list of tags) 754 | * 755 | * @return array associative of with capabilities 756 | */ 757 | public function getCapabilities() 758 | { 759 | return array( 760 | 'automatic_cleaning' => true, 761 | 'tags' => true, 762 | 'expired_read' => false, 763 | 'priority' => false, 764 | 'infinite_lifetime' => true, 765 | 'get_list' => false 766 | ); 767 | } 768 | } 769 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2017, Carl Oscar Aaro 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of Carl Oscar Aaro nor the names of its 15 | contributors may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Redis cache backend for Zend Framework by Carl Oscar Aaro 2 | ============= 3 | Requires the phpredis extension for PHP to enable PHP to communicate with the [Redis](http://redis.io/) key-value store. 4 | Start with installing the phpredis PHP extension available at https://github.com/nicolasff/phpredis 5 | 6 | Set up the Redis cache backend by invoking the following code somewhere in your project. 7 | 8 |
 9 | $redisCache = Zend_Cache::factory(
10 |     new Zend_Cache_Core(array(
11 |         'lifetime' => 3600,
12 |         'automatic_serialization' => true,
13 |     )),
14 |     new Extended_Cache_Backend_Redis(array(
15 |         'servers' => array(
16 |             array(
17 |                 'host' => '127.0.0.1',
18 |                 'port' => 6379,
19 |                 'dbindex' => 1,
20 |                 // 'persistent' => false, // not a persistent connection
21 |                 // 'auth' => true, // enable authentication
22 |                 // 'password' => 'mypwd000000', // password to authenticate on redis server
23 |             ),
24 |         ),
25 |         // 'key_prefix' => 'my_app', // if desire to add a prefix to all cache keys
26 |     ))
27 | );
28 | 
29 | 30 | Writing and reading from the cache works the same way as all other Zend Framework cache backends. 31 | 32 |
33 | $cacheKey = 'my_key';
34 | $data = 'e48e13207341b6bffb7fb1622282247b';
35 | 
36 | /* Save data to cache */
37 | $redisCache->save($data, $cacheKey, array('tag1', 'tag2'));
38 | 
39 | /* Load data from cache */
40 | $data = $redisCache->load($cacheKey);
41 | 
42 | /* Clear all keys with tag 'tag1' */
43 | $redisCache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array('tag1'));
44 | 
45 | /* Clear all cache (flush cache) */
46 | $redisCache->clean(Zend_Cache::CLEANING_MODE_ALL);
47 | 
48 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kalaspuff/redis-cache-zend-framework", 3 | "description": "Redis cache backend for Zend Framework", 4 | "keywords": ["redis", "zend"], 5 | "homepage": "https://github.com/kalaspuff/redis-cache-zend-framework", 6 | "license": "New BSD", 7 | "authors": [ 8 | { 9 | "name": "kalaspuff", 10 | "email": "carloscar@agigen.se", 11 | "homepage": "https://github.com/kalaspuff/", 12 | "role": "Developer" 13 | } 14 | ], 15 | "require": { 16 | "zendframework/zendframework1": ">=1.12.1" 17 | }, 18 | "autoload": { 19 | "classmap": ["."] 20 | } 21 | } --------------------------------------------------------------------------------