Installation
composer require emag-tech-labs/annotation-cache-bundle
Add to config/bundles.php (Symfony) or config/packages/annotation_cache.yaml (Laravel via Symfony bridge):
EmagTechLabs\AnnotationCacheBundle\AnnotationCacheBundle::class => ['all' => true],
Enable in services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
EmagTechLabs\AnnotationCacheBundle\:
resource: '../vendor/emag-tech-labs/annotation-cache-bundle/*'
exclude: '../vendor/emag-tech-labs/annotation-cache-bundle/{DependencyInjection,Tests,Resources}/*'
First Use Case Annotate a service method to cache its response:
use EmagTechLabs\AnnotationCacheBundle\Annotation\Cache;
class MyService {
/**
* @Cache(key="user_data_$id", ttl=3600)
*/
public function getUserData(int $id) {
return User::find($id)->toArray();
}
}
#[Cache(...)] for PHP 8+ attributes (requires bundle config adjustment).Annotation/Attribute Placement
@Cache or #[Cache] to methods in container-bound services.key: Dynamic string (supports $var interpolation).ttl: Time-to-live in seconds (default: null = no expiry).prefix: Optional cache prefix (e.g., app_).store: PSR-6 cache service ID (default: cache.app).Proxy Generation
Integration with Laravel
cache.array, cache.redis).
# config/packages/annotation_cache.yaml
emag_annotation_cache:
default_store: cache.redis
$this->app->bind(MyService::class, function ($app) {
return new MyService();
});
Dynamic Key Generation
#[Cache(key: "product_$id_$category")]
public function getProduct(int $id, string $category) { ... }
Cache Invalidation
$this->cache->delete('user_data_123');
CacheManager:
$this->container->get('emag_annotation_cache.cache_manager')->invalidate('user_data_*');
ProxyManager Conflicts
config/packages/annotation_cache.yaml:
emag_annotation_cache:
proxy_manager:
enabled: true
adapter: file
Annotation Parsing Failures
use_attributes: true in config:
emag_annotation_cache:
use_attributes: true
Circular Dependencies
@Cache(skip_if_missing: true).Key Collisions
key="data_$id" where $id is static) may overwrite cache unintentionally.data_$id_$timestamp).TTL Granularity
#[Cache(key: "volatile_data", ttl: 60)]
public function getVolatileData() {
if ($this->isDataFresh()) {
return $this->fetchFreshData();
}
return $this->cachedData;
}
Enable Logging
debug: true in config to log cache hits/misses:
emag_annotation_cache:
debug: true
Proxy Inspection
var_dump(get_class($this->container->get(MyService::class)));
Cache Store Verification
$this->container->has('cache.app'); // Should return true
Custom Cache Stores
Psr\Cache\CacheItemPoolInterface and bind it to the container:
services:
my_custom_cache:
class: App\Cache\MyCachePool
tags: ['cache.pool']
#[Cache(store: 'my_custom_cache', key: "my_key")]
Pre/Post Cache Hooks
EmagTechLabs\AnnotationCacheBundle\CacheableClassTrait to add logic before/after cache checks:
class MyService extends \EmagTechLabs\AnnotationCacheBundle\CacheableClassTrait {
protected function beforeCacheCheck(string $method, array $args) {
// Custom logic (e.g., auth checks)
}
}
Attribute Interceptors (PHP 8+)
EmagTechLabs\AnnotationCacheBundle\Attribute\CacheAttribute to add custom validation:
class CustomCacheAttribute extends CacheAttribute {
public function validate(array $args): void {
if (!in_array($args['key'], $this->allowedKeys)) {
throw new \InvalidArgumentException('Key not allowed');
}
}
}
How can I help you explore Laravel packages today?