{"id":24290773,"url":"https://github.com/emagtechlabs/annotation-cache-bundle","last_synced_at":"2026-01-11T10:45:33.111Z","repository":{"id":37811388,"uuid":"58373725","full_name":"eMAGTechLabs/annotation-cache-bundle","owner":"eMAGTechLabs","description":"Annotation based caching for services inside a symfony container","archived":false,"fork":false,"pushed_at":"2023-03-30T17:10:00.000Z","size":133,"stargazers_count":19,"open_issues_count":3,"forks_count":5,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-01-16T09:29:35.022Z","etag":null,"topics":["annotations","cache","cache-annotation","php","symfony","symfony-bundle"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eMAGTechLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null}},"created_at":"2016-05-09T12:11:13.000Z","updated_at":"2023-08-26T15:01:46.000Z","dependencies_parsed_at":"2023-07-14T21:31:28.894Z","dependency_job_id":null,"html_url":"https://github.com/eMAGTechLabs/annotation-cache-bundle","commit_stats":{"total_commits":86,"total_committers":7,"mean_commits":"12.285714285714286","dds":0.4534883720930233,"last_synced_commit":"048373efccd2ed01d7fb011679804a69ba23ba39"},"previous_names":["emagtechlabs/cache-bundle"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eMAGTechLabs%2Fannotation-cache-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eMAGTechLabs%2Fannotation-cache-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eMAGTechLabs%2Fannotation-cache-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eMAGTechLabs%2Fannotation-cache-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eMAGTechLabs","download_url":"https://codeload.github.com/eMAGTechLabs/annotation-cache-bundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234200683,"owners_count":18795206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotations","cache","cache-annotation","php","symfony","symfony-bundle"],"created_at":"2025-01-16T12:37:36.700Z","updated_at":"2025-09-25T14:31:19.799Z","avatar_url":"https://github.com/eMAGTechLabs.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Annotation Cache Bundle\n[![Packagist Version](https://img.shields.io/packagist/v/emag-tech-labs/annotation-cache-bundle)][package]\n[![Build Status](https://travis-ci.com/eMAGTechLabs/annotation-cache-bundle.svg?branch=master)][travis]\n[![Total Downloads](https://poser.pugx.org/emag-tech-labs/annotation-cache-bundle/downloads)][package]\n[![Latest Stable Version](https://poser.pugx.org/emag-tech-labs/annotation-cache-bundle/v/stable)][package]\n[![License](https://poser.pugx.org/emag-tech-labs/annotation-cache-bundle/license)][license]\n[![Coverage Status](https://coveralls.io/repos/github/eMAGTechLabs/annotation-cache-bundle/badge.svg?branch=master)][coveralls]\n\n----\nAnnotation based caching for method responses in services inside a Symfony container.\n\nThis bundle helps you to add caching with a simple annotation or attribute. You can store the cache in any class that \nimplements PSR-6: Caching Interface be it a simple array or a redis/memcache storage.\n\n## How it works\nThis bundle will scan all the methods from the defined services and look for the Cache annotation or attribute (for PHP 8+). \n\nFor all the services where the Cache annotation/attribute is found, it will create a proxy class (using ocramius/proxy-manager) \nthat extends the service class, include the CacheableClassTrait and overwrite the methods that have the Cache annotation/attribute.\n\nThe overwritten methods consist of a call to the `getCached` method that identifies the annotation details, gets the key,\ngets the Cache PSR-6 implementation and then gets the result from cache. If no data with the generated cache key is found, \nit will call the original method and then save the response in the given provider.\n\nThe bundle has a CompilerPass implementation that will search and overwrite the service definition with the proxy class\ncreated in the process explained above.\n\n## Installation\n\n### With Symfony Flex\nThe easiest way to install and configure the AnnotationCacheBundle with Symfony is by using\n[Symfony Flex](https://github.com/symfony/flex):\n\n```bash\n composer require symfony/flex ^1.0\n composer config extra.symfony.allow-contrib true\n composer require emag-tech-labs/annotation-cache-bundle\n```\n\nSymfony Flex will automatically register and configure the bundle.\n\n### Without Symfony Flex\nIf your application does not use Symfony Flex you can configure the bundle manually by following the steps below\n\n#### Step 1: Download the bundle\nOpen a command console, enter your project directory and execute the following command to download the latest stable \nversion of this bundle:\n\n```console\ncomposer require emag-tech-labs/annotation-cache-bundle\n```\n\n#### Step 2: Enable the bundle\nThen, enable the bundle by adding it to the list of registered bundles in the `config/bundles.php` file of your project:\n\n```php\n// config/bundles.php\n\nreturn [\n    // ...\n    EmagTechLabs\\AnnotationCacheBundle\\AnnotationCacheBundle::class =\u003e ['all' =\u003e true],\n];\n```\n\n#### Step 3: Configuration\nThe easiest way is to dump the config and copy it to `configs/packages/emag_annotation_cache.yaml`.\n\n```console\nbin/console config:dump-reference AnnotationCacheBundle\n```\n\n##### Configuration example\nYou have to configure the name of the service that is PSR6 compliant, that means it will have to implement \n`Psr\\Cache\\CacheItemPoolInterface`:\n\n```yaml\n# app/config/services.yaml\n\nservices:\n    cache.array:\n        class: Symfony\\Component\\Cache\\Adapter\\ArrayAdapter\n    cache.redis:\n        class: Symfony\\Component\\Cache\\Adapter\\RedisAdapter\n        arguments: ['@predis']\n```\n\n```yaml\n#configs/packages/emag_annotation_cache.yaml\n\n# Annotation Cache Bundle\nannotation_cache:\n    provider: \n        default: cache.redis\n        array: cache.array\n    ignore_namespaces:\n      - 'Symfony\\\\'\n      - 'Doctrine\\\\'\n    ignore_names:\n      - legacy\n      - type\n      - required\n```\n\n## Usage\nAdd the `Cache` annotation for the methods you want to cache.\n\nAnnotation parameters:\n- `cache` - cache prefix, __string__, _default value: null_ (eg: 'my_custom_prefix_')\n- `key` - name of argument(s) to include in cache key hash generation, __string, arg name separated by a comma__, \n  _default value: ''_ (eg: 'a,b')\n- `ttl` - time to store the cache in seconds, __int__, _default value: 600_ (eg: '3600')\n- `reset` - if the cache should be reset or not, __boolean__, _default value: false_ (eg: 'true')\n- `storage` - if multiple providers are defined, you can specify which provider to use, __string__, \n  _default value: 'default'_ (eg: 'array')\n\n\n### Annotations defined with Doctrine Annotations library\n```php\nuse EmagTechLabs\\AnnotationCacheBundle\\Annotation\\Cache;\n\n/**\n * @Cache(cache=\"\u003cput your prefix\u003e\", [key=\"\u003cname of argument to include in cache key separated by comma\u003e\",  [ttl=600, [reset=true, [storage=default ]]]])\n */\n```\n#### Example\n\n```php\nnamespace AppCacheBundle\\Service;\n\nuse EmagTechLabs\\AnnotationCacheBundle\\Annotation\\Cache;\n\nclass AppService\n{\n    /**\n     * @Cache(cache=\"app_high_cpu\", ttl=60)\n     *\n     * @return int\n     */\n    public function getHighCPUOperation(): int\n    {\n        sleep(10); // 'Simulate a time consuming operation';\n        return 20;\n    }\n}\n```\n\n### Annotations defined with PHP 8 attributes\n```php\nuse EmagTechLabs\\AnnotationCacheBundle\\Annotation\\Cache;\n\n #[Cache(cache:'\u003cput your prefix\u003e', key:'\u003cname of argument to include in cache key separated by comma\u003e', ttl:600, reset: true, storage: 'default')]\n```\n#### Example\n\n```php\nnamespace AppCacheBundle\\Service;\n\nuse EmagTechLabs\\AnnotationCacheBundle\\Annotation\\Cache;\n\nclass AppService\n{\n    #[Cache(cache:'app_high_cpu', ttl: 60)]\n    public function getHighCPUOperation(): int\n    {\n        sleep(10); // 'Simulate a time consuming operation';\n        return 20;\n    }\n}\n```\n\n### Use cases\nBelow you can find two ways you can use this Bundle\n\n#### Config\n```yaml\n# app/config/services.yaml\n\nservices:\n    cache.array:\n        class: Symfony\\Component\\Cache\\Adapter\\ArrayAdapter\n    cache.redis:\n        class: Symfony\\Component\\Cache\\Adapter\\RedisAdapter\n        arguments: ['@predis']\n```\n\n```yaml\n#configs/packages/emag_annotation_cache.yaml\n\n# Annotation Cache Bundle\nannotation_cache:\n    provider: \n        default: cache.array\n        redis: cache.redis\n    ignore_namespaces:\n      - 'Symfony\\\\'\n```\n\n#### Service Code\nThis bundle can be used in multiple ways, two of them are shown below.\n\nThe first case is the most common one, where you have a method that does multiple time-consuming operations, and you want\nto cache the response in redis with a prefix (simple_time_consuming_operation_) for a given time (60s in the case below).\nThe logic here is to look for the value in redis, and if not found, run the actual method, get the result and cache it\nfor further use taking into account the arguments passed in the `@Cache` annotation.\n\nThe second case could be used if you want to generate the cache in a command and have it already warmed up, or maybe \nupdate the cache when a certain event is triggered, or you update the information in a database. Based on the example below, \nyou could set a cron to run every ~3000 seconds and that will recreate the cache before it expires. Because we are using \nthe same cache prefix and keys, when the same argument values are passed for both methods(`getTimeConsumingOperationValueWithReset` \nand `getTimeConsumingOperationValue`), the generated cache key will be the same, in this case: \ntime_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600.\nThat means that both methods will write (and read) the cache in (from) the same cache key. Because the second method has \nthe `reset` argument set to true, any call to the second method will overwrite the cache value in the key\ntime_consuming_operation_7fe49b314fb356bee76dbd3b8716b4d5ab5db600 with the new result of the function.\n\n\n```php\nnamespace AppCacheBundle\\Service;\n\nuse EmagTechLabs\\AnnotationCacheBundle\\Annotation\\Cache;\n\nclass AppService\n{\n    /**\n     * @Cache(cache=\"simple_time_consuming_operation_\", ttl=60, storage=\"redis\")\n     *\n     * @param int $a\n     * @param int $b\n     * \n     * @return int\n     */\n    public function getSimpleTimeConsumingOperationValue(int $a, int $b): int\n    {\n        sleep(10); // 'Simulate a time consuming operation';\n        return $a + $b;\n    }\n    \n    #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, storage: 'redis')]\n    public function getTimeConsumingOperationValue(int $a, int $b): int\n    {\n        return $this-\u003egetTimeConsumingOperationValueWithReset($a, $b);\n    }\n    \n    #[Cache(cache:'time_consuming_operation_', key: 'a,b', ttl: 3600, reset: true, storage: 'redis')]\n    public function getTimeConsumingOperationValueWithReset(int $a, int $b): int\n    {\n        sleep(10); // 'Simulate a time consuming operation';\n        return $a + $b;\n    }\n}\n```\n\n#### Service calls\n```php\n// from controller\n/** AppService $appService */\n$appService-\u003egetTimeConsumingOperationValue(1, 2);\n\n// from command\n/** AppService $appService */\n$appService-\u003egetTimeConsumingOperationValueWithReset(1, 2);\n```\n\n\n## Contributing\nThanks for your interest in contributing! There are many ways to contribute to this project. Get started [here](CONTRIBUTING.md).\n\n\n[license]: https://github.com/emag-tech-labs/annotation-cache-bundle/blob/master/LICENSE\n[package]: https://packagist.org/packages/emag-tech-labs/annotation-cache-bundle\n[travis]: https://travis-ci.com/eMAGTechLabs/annotation-cache-bundle\n[coveralls]: https://coveralls.io/github/eMAGTechLabs/annotation-cache-bundle?branch=master","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femagtechlabs%2Fannotation-cache-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femagtechlabs%2Fannotation-cache-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femagtechlabs%2Fannotation-cache-bundle/lists"}