Skip to content

sebsastianek/caching-attribute

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CachingAttribute Library

Still in development!

Overview

AnnotatedCache is a PHP library that provides an attribute-driven caching solution. It allows developers to cache function or method results dynamically based on provided attributes.

Features

  • Attribute-Based Caching: Use PHP attributes to define caching behavior on methods.
  • Custom Cache Key Generation: Generate cache keys dynamically based on method parameters and user context.
  • Pluggable Implementations: Easily integrate with frameworks like Laminas and Symfony.
  • User-Specific Caching: Optionally cache results separately for different users.

Installation

Install the library via Composer:

composer require annotated-cache

Usage

Example with a Plain PHP Service

Here’s a basic example of using AnnotatedCache with the CachingTrait in a standalone PHP application:

use AnnotatedCache\Attributes\Cached; 
use AnnotatedCache\Cache\CacheFactory; 
use AnnotatedCache\Cache\CacheKeyGenerator; 
use AnnotatedCache\Interceptor\CacheInterceptor; 
use Psr\Cache\CacheItemPoolInterface; 
use AnnotatedCache\Trait\CachingTrait; 
 
class MyService 
{ 
    use CachingTrait; 
    
    #[Cached(ttl: 600, userSpecific: true)] 
    public function getData(string $key): string 
    { 
        return 'Data for ' . $key; 
    } 
} 
 
$cacheBuilder = function (string $name): CacheItemPoolInterface { 
    return new SomeCacheImplementation(); // Replace with actual PSR-6 implementation 
}; 

$userIdentityProvider = new SomeUserIdentityProvider(); // Replace with actual user provider 
$cacheFactory = new CacheFactory($cacheBuilder); 
$keyGenerator = new CacheKeyGenerator($userIdentityProvider); 
$cacheInterceptor = new CacheInterceptor($cacheFactory, $keyGenerator); 
 
$service = new MyService(); 
$service->setCacheInterceptor($cacheInterceptor); 
 
$result = $service->getData('myKey'); 
echo $result; // Cached result 

Framework Integrations

Laminas Integration

To integrate AnnotatedCache into a Laminas application, you can use a factory pattern with a delegator.

Configuration Example

return [
    'dependencies' => [
        'factories' => [
            CacheInterceptor::class => function ($container) {
                return new CacheInterceptor(
                    $container->get(CacheFactory::class),
                    $container->get(CacheKeyGeneratorInterface::class)
                );
            },
        ],
        'delegators' => [
            MyService::class => [
                MethodInterceptorDelegatorFactory::class,
            ],
        ],
    ],
];

MethodInterceptorDelegatorFactory

namespace MyApp\Factory;

use AnnotatedCache\Interceptor\MethodInterceptor;
use Psr\Container\ContainerInterface;

class MethodInterceptorDelegatorFactory
{
    public function __invoke(ContainerInterface $container, string $name, callable $callback)
    {
        $service = $callback();
        $cacheInterceptor = $container->get(CacheInterceptor::class);
        return new MethodInterceptor($service, $cacheInterceptor);
    }
}

Symfony Integration

To integrate AnnotatedCache into a Symfony application, use a compiler pass to wrap your services.

Configuration Example

services:
  AnnotatedCache\Interceptor\CacheInterceptor:
    arguments:
      $cacheFactory: '@App\Cache\CacheFactory'
      $keyGenerator: '@App\Service\CacheKeyGenerator'

  App\Service\MyService:
    tags:
      - { name: 'annotated_cache.intercept' }

  App\Service\AnotherService:
    tags:
      - { name: 'annotated_cache.intercept' }

Custom Compiler Pass

namespace App\DependencyInjection\Compiler;

use AnnotatedCache\Interceptor\MethodInterceptor;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class AnnotatedCachePass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        foreach ($container->findTaggedServiceIds('annotated_cache.intercept') as $serviceId => $tags) {
            $originalServiceId = $serviceId . '.original';
            $container->setAlias($originalServiceId, $serviceId);

            $container->getDefinition($serviceId)
                ->setDecoratedService($originalServiceId)
                ->setClass(MethodInterceptor::class)
                ->setArguments([
                    new Reference($originalServiceId),
                    new Reference('AnnotatedCache\Interceptor\CacheInterceptor'),
                ]);
        }
    }
}

Register the Compiler Pass

// src/Kernel.php

use App\DependencyInjection\Compiler\AnnotatedCachePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;

class AppKernel extends Kernel
{
    protected function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new AnnotatedCachePass());
    }
}

Testing

Run tests with PHPUnit:

vendor/bin/phpunit

License

This library is open-sourced software licensed under the MIT license.

Contributing

Contributions are welcome! If you’d like to contribute, please fork the repository and submit a pull request.

Support

If you encounter any issues or have questions, feel free to open an issue in the GitHub repository.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages