emag-tech-labs / cache-bundle
Requires
- php: ^8.0
- doctrine/annotations: ^1.11
- friendsofphp/proxy-manager-lts: ^1.0
- psr/cache: ^1.0|^2.0|^3.0
- psr/log: ^1.1|^2.0|^3.0
- symfony/dependency-injection: ^4.0||^5.1||^6.0
- symfony/yaml: ^4.0||^5.1||^6.0
Requires (Dev)
- infection/infection: ^0.21.0
- php-coveralls/php-coveralls: ^2.4
- phpmd/phpmd: ^2.9
- phpmetrics/phpmetrics: ^2.7
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^1.0
- phpstan/phpstan-phpunit: ^1.1
- phpunit/phpunit: ^8.5||^9.0
- squizlabs/php_codesniffer: ^3.5
- symfony/cache: ^4.0||^5.1|^6.0
- symfony/framework-bundle: ^4.0||^5.1|^6.0
- symfony/monolog-bundle: ^3.6
- vimeo/psalm: ^4.4
Suggests
- symfony/cache: ^4.0||^5.1||^6.0
README
对称容器内部服务方法响应的注解缓存。
此包可以帮助您通过简单的注解或属性添加缓存。您可以将缓存存储在任何实现PSR-6:缓存接口的类中,无论是简单的数组还是redis/memcache存储。
工作原理
此包将扫描所有定义的服务中的所有方法,寻找缓存注解或属性(对于PHP 8+)。
对于找到缓存注解/属性的任何服务,它将创建一个代理类(使用ocramius/proxy-manager),该类扩展了服务类,包含CacheableClassTrait并覆盖具有缓存注解/属性的方法。
覆盖的方法包括调用getCached
方法,该方法识别注解细节,获取键,获取Cache PSR-6实现,然后从缓存中获取结果。如果未找到具有生成的缓存键的数据,它将调用原始方法,然后将响应保存到指定的提供者。
此包有一个CompilerPass实现,将搜索并覆盖服务定义,使用上述过程中创建的代理类。
安装
使用Symfony Flex
通过使用 Symfony Flex 安装和配置AnnotationCacheBundle是Symfony中最简单的方法。
composer require symfony/flex ^1.0
composer config extra.symfony.allow-contrib true
composer require emag-tech-labs/annotation-cache-bundle
Symfony Flex将自动注册和配置包。
不使用Symfony Flex
如果您的应用程序不使用Symfony Flex,您可以按照以下步骤手动配置包
步骤 1:下载包
打开命令行,进入您的项目目录,并执行以下命令以下载此包的最新稳定版本
composer require emag-tech-labs/annotation-cache-bundle
步骤 2:启用包
然后,通过将其添加到项目config/bundles.php
文件中注册的包列表中,启用该包。
// config/bundles.php return [ // ... EmagTechLabs\AnnotationCacheBundle\AnnotationCacheBundle::class => ['all' => true], ];
步骤 3:配置
最简单的方法是将配置导出到configs/packages/emag_annotation_cache.yaml
。
bin/console config:dump-reference AnnotationCacheBundle
配置示例
您必须配置PSR6兼容的服务名称,这意味着它必须实现Psr\Cache\CacheItemPoolInterface
。
# app/config/services.yaml services: cache.array: class: Symfony\Component\Cache\Adapter\ArrayAdapter cache.redis: class: Symfony\Component\Cache\Adapter\RedisAdapter arguments: ['@predis']
#configs/packages/emag_annotation_cache.yaml # Annotation Cache Bundle annotation_cache: provider: default: cache.redis array: cache.array ignore_namespaces: - 'Symfony\\' - 'Doctrine\\' ignore_names: - legacy - type - required
用法
为要缓存的函数添加Cache
注解。
注解参数
cache
- 缓存前缀,字符串,默认值: null(例如:'my_custom_prefix_')key
- 包含在缓存键哈希生成中的参数名称,字符串,用逗号分隔的参数名称,默认值: ''(例如:'a,b')ttl
- 缓存在秒数,整数,默认值: 600(例如:'3600')reset
- 如果缓存应该重置或不重置,布尔值,默认值: false(例如:'true')storage
- 如果定义了多个提供者,可以指定使用哪个提供者,字符串,默认值: 'default'(例如:'array')
使用Doctrine Annotations库定义的注解
use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache; /** * @Cache(cache="<put your prefix>", [key="<name of argument to include in cache key separated by comma>", [ttl=600, [reset=true, [storage=default ]]]]) */
示例
namespace AppCacheBundle\Service; use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache; class AppService { /** * @Cache(cache="app_high_cpu", ttl=60) * * @return int */ public function getHighCPUOperation(): int { sleep(10); // 'Simulate a time consuming operation'; return 20; } }
使用PHP 8属性定义的注解
use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache; #[Cache(cache:'<put your prefix>', key:'<name of argument to include in cache key separated by comma>', ttl:600, reset: true, storage: 'default')]
示例
namespace AppCacheBundle\Service; use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache; class AppService { #[Cache(cache:'app_high_cpu', ttl: 60)] public function getHighCPUOperation(): int { sleep(10); // 'Simulate a time consuming operation'; return 20; } }
用例
以下您可以找到两种使用此Bundle的方法
配置
# app/config/services.yaml services: cache.array: class: Symfony\Component\Cache\Adapter\ArrayAdapter cache.redis: class: Symfony\Component\Cache\Adapter\RedisAdapter arguments: ['@predis']
#configs/packages/emag_annotation_cache.yaml # Annotation Cache Bundle annotation_cache: provider: default: cache.array redis: cache.redis ignore_namespaces: - 'Symfony\\'
服务代码
此bundle可以用多种方式使用,以下展示了两种方式。
第一种情况是最常见的,您有一个执行多个耗时操作的函数,并希望将响应缓存到redis中,使用前缀(simple_time_consuming_operation_)和给定的时间(以下示例中的60s)进行缓存。这里的逻辑是先在redis中查找值,如果未找到,则执行实际的方法,获取结果并将其缓存以供将来使用,同时考虑在@Cache
注解中传递的参数。
第二种情况可以用于在命令中生成缓存并使其预先加载,或者在某些事件触发时更新缓存,或者更新数据库中的信息。根据以下示例,您可以设置一个cron作业每3000秒运行一次,这样在缓存过期之前将重新创建缓存。因为我们使用相同的缓存前缀和键,当两个方法(getTimeConsumingOperationValueWithReset
和getTimeConsumingOperationValue
)传递相同的参数值时,生成的缓存键将是相同的,在这种情况下:time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600。这意味着两个方法都将写入(和读取)相同的缓存键。因为第二个方法将reset
参数设置为true,所以对第二个方法的任何调用都将覆盖键time_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600中的缓存值,以函数的新结果覆盖。
namespace AppCacheBundle\Service; use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache; class AppService { /** * @Cache(cache="simple_time_consuming_operation_", ttl=60, storage="redis") * * @param int $a * @param int $b * * @return int */ public function getSimpleTimeConsumingOperationValue(int $a, int $b): int { sleep(10); // 'Simulate a time consuming operation'; return $a + $b; } #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, storage: 'redis')] public function getTimeConsumingOperationValue(int $a, int $b): int { return $this->getTimeConsumingOperationValueWithReset($a, $b); } #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, reset: true, storage: 'redis')] public function getTimeConsumingOperationValueWithReset(int $a, int $b): int { sleep(10); // 'Simulate a time consuming operation'; return $a + $b; } }
服务调用
// from controller /** AppService $appService */ $appService->getTimeConsumingOperationValue(1, 2); // from command /** AppService $appService */ $appService->getTimeConsumingOperationValueWithReset(1, 2);
贡献
感谢您对贡献的兴趣!有许多方法可以为这个项目做出贡献。从这里开始。