tbbc/cache-bundle

Symfony 扩展包 - 缓存抽象和方法注解用于控制缓存

安装: 13 019

依赖项: 0

建议者: 0

安全: 0

星级: 36

关注者: 9

分支: 8

开放问题: 10

类型:symfony-bundle

v1.0.0 2014-04-18 14:16 UTC

This package is not auto-updated.

Last update: 2024-09-14 16:24:03 UTC


README

添加 缓存抽象方法注解 以控制缓存。Cache 组件的当前实现是 Doctrine\Common\Cache 的包装器(代理)。

状态

Build Status Scrutinizer Code Quality Downloads Stable release

概览

TbbcCacheBundle 集成 Symfony 与非侵入式应用缓存管理系统。它通过使用 AOP 机制和 PHP 语言表达式,为开发者提供基于注解的缓存控制。

<?php

namespace My\Manager;

use My\Model\Product;
use Tbbc\CacheBundle\Annotation\Cacheable;
use Tbbc\CacheBundle\Annotation\CacheUpdate;
use Tbbc\CacheBundle\Annotation\CacheEvict;

class ProductManager
{
    /**
     * @Cacheable(caches="products", key="sku")
     */
    public function getProduct($sku, $type = 'book')
    {
        // fetch a product from a repository or whatever
        $product = $this->productRepository->getByType($sku, 'book');

        return $product;
    }

    /**
     * @CacheUpdate(caches="products", key="product.getSku()")
     */
    public function updateProduct(Product $product)
    {
        $product = $this->productRepository->save($product);

        return $product;
    }

    /**
     * @CacheEvict(caches="products", key="product.getSku()")
     */
    public function removeProduct(Product $product)
    {
        $product = $this->productRepository->remove($product);
    }
}

特性

  • 支持 @Cacheable@CacheUpdate@CacheEvict 注解
  • TTL 策略,允许您自定义缓存保留时间
  • 命名空间缓存管理器
  • 多个缓存管理器
    • Doctrine/ArrayCache
    • Doctrine/ApcCache
    • Doctrine/MemcachedCache
    • Doctrine/RedisCache
  • Symfony Debug Toolbar 集成

文档

安装

首先,使用 composer 安装扩展包

$ php composer.phar require tbbc/cache-bundle

接下来,在 app/AppKernel.php 中激活扩展包

<?php

// ...
    public function registerBundles()
    {
        $bundles = array(
            //...
            new Tbbc\CacheBundle\TbbcCacheBundle(),
        );

        // ...
    }

配置

services:
    my_manager.product:
        class: My\Manager\ProductManager
        tags:
            - { name: tbbc_cache.cache_eligible }

tbbc_cache:
    annotations: { enabled: true }
    manager: simple_cache
    key_generator: simple_hash
    metadata:
        use_cache: true # Whether or not use metadata cache
        cache_dir: %kernel.cache_dir%/tbbc_cache
    cache:
        products:
            type: memcached
            servers:
                memcached-01: { host: localhost, port: 11211 }

注意:如果您想使用注解来使用此服务,则必须在服务定义中强制使用 tbbc_cache.cache_eligible 标签。

使用

基于注解的缓存(推荐)

推荐

如果有人希望避免每次添加一些缓存逻辑时都重复代码,则扩展包可以通过使用 AOP 方法及注解来自动化此过程。

扩展包提供了以下注解

@Cacheable 注解

@Cacheable 注解用于将方法的结果自动存储到缓存中。

当调用标记了 @Cacheable 注解的方法时,扩展包会检查缓存中是否存在条目。如果找到,则返回缓存结果而无需实际执行方法。

如果没有找到缓存条目,则执行方法,并自动将结果存储到缓存中。

<?php

namespace My\Manager;

use My\Model\Product;

use Tbbc\CacheBundle\Annotation\Cacheable;

class ProductManager
{
    /**
     * @Cacheable(caches="products", key="sku")
     */
    public function getProduct($sku, $type = 'book')
    {
        // fetch a product from a repository or whatever
        $product = $this->productRepository->getByType($sku, 'book');

        return $product;
    }
}

@CacheEvict 注解

@CacheEvict 注解允许方法触发缓存填充或删除。

当方法被标记为 @CacheEvict 注解时,扩展包将执行该方法,然后自动尝试删除带有提供键的缓存条目。

<?php

namespace My\Manager;

use My\Model\Product;

use Tbbc\CacheBundle\Annotation\CacheEvict;

class ProductManager
{
    /**
     * @CacheEvict(caches="products", key="product.getSku()")
     */
    public function removeProduct(Product $product)
    {
        // saving product ...
    }
}

也可以通过将 allEntries 参数设置为 true 来完全清除缓存。

⚠️ 重要提示:使用 allEntries 选项时要非常小心,如果您为不同命名空间使用相同的缓存管理器,则整个缓存管理器将被清除。这是当前底层 Doctrine Cache 库的限制。

<?php

namespace My\Manager;

use My\Model\Product;

use Tbbc\CacheBundle\Annotation\CacheEvict;

class ProductManager
{
    /**
     * @CacheEvict(caches="products", allEntries=true)
     */
    public function removeProduct(Product $product)
    {
        // saving product ...
    }
}

注意:如果您还提供了 key,它将被忽略,缓存将被清除。

@CacheUpdate 注解

@CacheUpdate 注解对于需要更新缓存而不干扰方法执行的情况非常有用。

当一个方法被@CacheUpdate注解标记时,组件将始终执行该方法,然后将自动尝试使用方法结果更新缓存条目。

<?php

namespace My\Manager;

use My\Model\Product;

use Tbbc\CacheBundle\Annotation\CacheUpdate;

class ProductManager
{
    /**
     * @CacheUpdate(caches="products", key="product.getSku()")
     */
    public function updateProduct(Product $product)
    {
        // saving product....

        return $product;
    }
}

表达式语言

对于键生成,可以使用Symfony表达式语言

/**
 * @CacheUpdate(caches="products", key="product.getSku()")
 */
 public function updateProduct(Product $product)
 {
    // do something
 }

表达式语言允许您检索传递给方法的所有参数,并使用它来生成缓存键。

标准缓存使用(无注解)

必须将CacheManager实例注入到需要缓存管理的服务中。

CacheManager提供对每个配置的缓存的访问(请参阅配置部分)。每个缓存实现CacheInterface

使用

<?php

namespace My\Manager;

use Tbbc\CacheBundle\Annotation\Cacheable;

class ProductManager
{
    private $cacheManager;
    private $keyGenerator;

    public function __construct(CacheManagerInterface $cacheManager, KeyGeneratorInterface $keyGenerator)
    {
        $this->cacheManager = $cacheManager;
        $this->keyGenerator = $keyGenerator;
    }


    public function getProduct($sku, $type = 'book')
    {
        $cacheKey   = $this->keyGenerator->generateKey($sku);
        $cache      = $this->cacheManager->getCache('products');

        if ($product = $cache->get($cacheKey)) {
            return $product;
        }

        $product = $this->productRepository->findProductBySkuAndType($sku, $type);

        $cache->set($cacheKey, $product);

        return $product;
    }

    public function saveProduct(Product $product)
    {
        $this->productRepository->save($product);

        $cacheKey   = $this->keyGenerator->generateKey($product->getSku());
        $cache      = $this->cacheManager->getCache('products');

        $cache->delete($cacheKey);
    }
}

自定义缓存管理器

默认情况下,该组件提供了一个SimpleCacheManager,但可以使用自定义缓存管理器代替默认的缓存管理器,并且必须实现CacheManagerInterface

键生成

键生成由开发者决定,但为了方便,该组件自带了一些键生成逻辑。

注意:在基于注解的缓存中使用时,使用键生成器是强制性的。

默认情况下,该组件提供了一个SimpleHashKeyGenerator,它基本上使用md5算法对每个参数进行编码,并返回结果的md5散列。

出于测试目的,您还可以使用LiteralKeyGenerator,它构建类似slug的键。

注意:这两个生成器不支持非标量键,如对象。

您可以通过在config.yml中设置key_generator键来覆盖键生成器。

允许的值是:simple_hashliteral或自定义键生成器服务的ID

自定义键生成

可以使用自定义键生成器代替默认的键生成器,并且必须实现KeyGeneratorInterface

TTL 策略

由于此组件提供缓存抽象,并非所有缓存提供程序都支持或以相同的方式处理TTL,因此必须在每个缓存配置选项中定义TTL策略(当支持选项时)。

示例

tbbc_cache:
    annotations: { enabled: true }
    manager: simple_cache
    cache:
        products:
            type: memcached
            ttl: 86400 # 1 day
            servers:
                memcached-01: { host: localhost, port: 11211 }
        user_feeds:
            type: memcached
            ttl: 0 # infinite (same as omitting the option)
        followers_list:
            type: apc
            ttl: 1296000 # 15 days
        activity_counters:
            type: redis
            ttl: 3600 # 1 hour
            server:
                host: 127.0.0.1
                port: 6379

Symfony debug toolbar 集成

调试缓存操作往往很痛苦。为了方便这项工作,该组件直接在Symfony调试工具栏中添加了一些有用的实时信息。

以下是一些关于它将显示的信息的截图

已知限制

带有“allEntries”选项的缓存清除操作

由于缓存在Doctrine中的管理方式,尤其是在不同的缓存系统中处理的方式,使用带有“allEntries”选项的“CacheEvict”操作可能会导致不良行为。

警告:如果您使用不同的缓存命名空间但属于同一缓存实例(例如单个memcached服务器),则“allEntries”选项将清除所有命名空间中的所有缓存条目。这意味着它将清除整个实例的缓存。

Doctrine实体缓存

目前不支持自动缓存Doctrine实体。如果您需要缓存实体,您必须实现自己的逻辑。

实现这一点的 一种方法是通过覆盖注解和元数据来添加一个序列化“类型”选项,然后通过挂钩缓存事件来手动管理序列化/反序列化操作。

<?php

namespace My\EventListener;

use My\CacheBundle\SerializedCacheValue;

use Tbbc\CacheBundle\Event\CacheHitEvent;
use Tbbc\CacheBundle\Event\CacheUpdateEvent;
use JMS\SerializerBundle\Serializer\SerializerInterface;
use Tbbc\CacheBundle\Cache\CacheManagerInterface;

class CacheEventListener
{
    private $serializer;
    private $cacheManager;

    public function __construct(SerializerInterface $serializer, CacheManagerInterface $cacheManager)
    {
        $this->serializer = $serializer;
        $this->cacheManager = $cacheManager;
    }

    public function onAfterCacheHit(CacheHitEvent $event)
    {
        $value = $event->getValue();
        if ($value instanceof SerializedCacheValue) {
            $value = $this->serializer->deserialize($value->data, $value->type, 'json');
            $event->setValue($value);
        }
    }

    public function onAfterCacheUpdate(CacheUpdateEvent $event)
    {
        $cache = $event->getCache();
        $key = $event->getKey();
        $metadata = $event->getMetadata();

        if (null !== $metadata->type) {
            $serializedValue = $this->serializer->serialize($event->getValue(), 'json');
            $value = new SerializedCacheValue($metadata->type, $serializedValue);
            $this->cacheManager->getCache($cache)->set($key, $value);
        }
    }
}

测试

安装开发依赖项

$ composer install --dev

运行测试套件

$ vendor/bin/phpunit

许可

此组件采用MIT许可。请参阅组件中的完整许可协议

Resources/meta/LICENSE

The Big Brains Company - Logo