acc-create-psr6-cache

Generates PSR-6 Cache implementation for PHP 8.5. Creates CacheItemPoolInterface and CacheItemInterface implementations with TTL handling and deferred saves. Includes unit tests.

174 stars

Best use case

acc-create-psr6-cache is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Generates PSR-6 Cache implementation for PHP 8.5. Creates CacheItemPoolInterface and CacheItemInterface implementations with TTL handling and deferred saves. Includes unit tests.

Teams using acc-create-psr6-cache should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/acc-create-psr6-cache/SKILL.md --create-dirs "https://raw.githubusercontent.com/majiayu000/claude-skill-registry/main/skills/data/acc-create-psr6-cache/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/acc-create-psr6-cache/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How acc-create-psr6-cache Compares

Feature / Agentacc-create-psr6-cacheStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Generates PSR-6 Cache implementation for PHP 8.5. Creates CacheItemPoolInterface and CacheItemInterface implementations with TTL handling and deferred saves. Includes unit tests.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# PSR-6 Cache Generator

## Overview

Generates PSR-6 compliant cache implementations following `Psr\Cache\CacheItemPoolInterface` and `Psr\Cache\CacheItemInterface`.

## When to Use

- Complex caching with cache items as objects
- Need for deferred/batched saves
- Building cache frameworks
- Need for cache item metadata

## Generated Components

| Component | Description | Location |
|-----------|-------------|----------|
| CacheItemPool | Pool implementation | `src/Infrastructure/Cache/` |
| CacheItem | Item implementation | `src/Infrastructure/Cache/` |
| Unit Tests | PHPUnit tests | `tests/Unit/Infrastructure/Cache/` |

## Template: Cache Item

```php
<?php

declare(strict_types=1);

namespace App\Infrastructure\Cache;

use DateInterval;
use DateTimeImmutable;
use DateTimeInterface;
use Psr\Cache\CacheItemInterface;

final class CacheItem implements CacheItemInterface
{
    private mixed $value = null;
    private bool $isHit = false;
    private ?DateTimeImmutable $expiration = null;

    public function __construct(
        private readonly string $key,
    ) {
    }

    public function getKey(): string
    {
        return $this->key;
    }

    public function get(): mixed
    {
        return $this->isHit ? $this->value : null;
    }

    public function isHit(): bool
    {
        return $this->isHit;
    }

    public function set(mixed $value): static
    {
        $this->value = $value;
        $this->isHit = true;

        return $this;
    }

    public function expiresAt(?DateTimeInterface $expiration): static
    {
        $this->expiration = $expiration instanceof DateTimeImmutable
            ? $expiration
            : ($expiration !== null
                ? DateTimeImmutable::createFromInterface($expiration)
                : null);

        return $this;
    }

    public function expiresAfter(int|DateInterval|null $time): static
    {
        if ($time === null) {
            $this->expiration = null;
        } elseif ($time instanceof DateInterval) {
            $this->expiration = (new DateTimeImmutable())->add($time);
        } else {
            $this->expiration = (new DateTimeImmutable())->modify("+{$time} seconds");
        }

        return $this;
    }

    public function getExpiration(): ?DateTimeImmutable
    {
        return $this->expiration;
    }

    public function isExpired(): bool
    {
        if ($this->expiration === null) {
            return false;
        }

        return $this->expiration < new DateTimeImmutable();
    }

    public function markAsHit(): void
    {
        $this->isHit = true;
    }

    public function markAsMiss(): void
    {
        $this->isHit = false;
    }
}
```

## Template: Array Cache Pool

```php
<?php

declare(strict_types=1);

namespace App\Infrastructure\Cache;

use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;

final class ArrayCachePool implements CacheItemPoolInterface
{
    /** @var array<string, CacheItem> */
    private array $items = [];

    /** @var array<string, CacheItem> */
    private array $deferred = [];

    public function getItem(string $key): CacheItemInterface
    {
        $this->validateKey($key);

        if (isset($this->deferred[$key])) {
            return clone $this->deferred[$key];
        }

        if (isset($this->items[$key])) {
            $item = $this->items[$key];

            if (!$item->isExpired()) {
                return clone $item;
            }

            unset($this->items[$key]);
        }

        $item = new CacheItem($key);
        $item->markAsMiss();

        return $item;
    }

    /** @return iterable<string, CacheItemInterface> */
    public function getItems(array $keys = []): iterable
    {
        $items = [];

        foreach ($keys as $key) {
            $items[$key] = $this->getItem($key);
        }

        return $items;
    }

    public function hasItem(string $key): bool
    {
        $this->validateKey($key);

        return $this->getItem($key)->isHit();
    }

    public function clear(): bool
    {
        $this->items = [];
        $this->deferred = [];

        return true;
    }

    public function deleteItem(string $key): bool
    {
        $this->validateKey($key);

        unset($this->items[$key], $this->deferred[$key]);

        return true;
    }

    public function deleteItems(array $keys): bool
    {
        foreach ($keys as $key) {
            $this->deleteItem($key);
        }

        return true;
    }

    public function save(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return false;
        }

        $this->items[$item->getKey()] = $item;
        unset($this->deferred[$item->getKey()]);

        return true;
    }

    public function saveDeferred(CacheItemInterface $item): bool
    {
        if (!$item instanceof CacheItem) {
            return false;
        }

        $this->deferred[$item->getKey()] = $item;

        return true;
    }

    public function commit(): bool
    {
        foreach ($this->deferred as $item) {
            $this->save($item);
        }

        $this->deferred = [];

        return true;
    }

    private function validateKey(string $key): void
    {
        if ($key === '') {
            throw new InvalidArgumentException('Cache key cannot be empty');
        }

        if (preg_match('/[{}()\/\\\\@:]/', $key)) {
            throw new InvalidArgumentException(
                'Cache key contains reserved characters: {}()/\\@:',
            );
        }
    }
}
```

## Template: Unit Test

```php
<?php

declare(strict_types=1);

namespace App\Tests\Unit\Infrastructure\Cache;

use App\Infrastructure\Cache\ArrayCachePool;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

#[Group('unit')]
#[CoversClass(ArrayCachePool::class)]
final class ArrayCachePoolTest extends TestCase
{
    private ArrayCachePool $pool;

    protected function setUp(): void
    {
        $this->pool = new ArrayCachePool();
    }

    #[Test]
    public function it_returns_miss_for_nonexistent_item(): void
    {
        $item = $this->pool->getItem('nonexistent');

        self::assertFalse($item->isHit());
        self::assertNull($item->get());
    }

    #[Test]
    public function it_saves_and_retrieves_item(): void
    {
        $item = $this->pool->getItem('key');
        $item->set('value');
        $this->pool->save($item);

        $retrieved = $this->pool->getItem('key');

        self::assertTrue($retrieved->isHit());
        self::assertSame('value', $retrieved->get());
    }

    #[Test]
    public function it_handles_deferred_saves(): void
    {
        $item1 = $this->pool->getItem('key1')->set('value1');
        $item2 = $this->pool->getItem('key2')->set('value2');

        $this->pool->saveDeferred($item1);
        $this->pool->saveDeferred($item2);

        self::assertTrue($this->pool->getItem('key1')->isHit());

        $this->pool->commit();

        self::assertTrue($this->pool->getItem('key1')->isHit());
        self::assertTrue($this->pool->getItem('key2')->isHit());
    }

    #[Test]
    public function it_deletes_item(): void
    {
        $item = $this->pool->getItem('key')->set('value');
        $this->pool->save($item);

        $this->pool->deleteItem('key');

        self::assertFalse($this->pool->hasItem('key'));
    }

    #[Test]
    public function it_clears_all_items(): void
    {
        $this->pool->save($this->pool->getItem('key1')->set('value1'));
        $this->pool->save($this->pool->getItem('key2')->set('value2'));

        $this->pool->clear();

        self::assertFalse($this->pool->hasItem('key1'));
        self::assertFalse($this->pool->hasItem('key2'));
    }
}
```

## Usage Example

```php
<?php

use App\Infrastructure\Cache\ArrayCachePool;

$pool = new ArrayCachePool();

// Get item (miss)
$item = $pool->getItem('user_123');

if (!$item->isHit()) {
    $user = $userRepository->find(123);
    $item->set($user);
    $item->expiresAfter(3600); // 1 hour
    $pool->save($item);
}

$user = $item->get();

// Deferred saves
$item1 = $pool->getItem('key1')->set('value1');
$item2 = $pool->getItem('key2')->set('value2');

$pool->saveDeferred($item1);
$pool->saveDeferred($item2);
$pool->commit();
```

## Requirements

```json
{
    "require": {
        "psr/cache": "^3.0"
    }
}
```

## See Also

- `references/templates.md` - Redis and file-based implementations
- `references/examples.md` - Integration examples

Related Skills

acc-create-value-object

181
from majiayu000/claude-skill-registry

Generates DDD Value Objects for PHP 8.5. Creates immutable, self-validating objects with equality comparison. Includes unit tests.

acc-create-use-case

181
from majiayu000/claude-skill-registry

Generates Application Use Cases for PHP 8.5. Creates orchestration services that coordinate domain objects, handle transactions, and dispatch events. Includes unit tests.

acc-create-unit-test

181
from majiayu000/claude-skill-registry

Generates PHPUnit unit tests for PHP 8.5. Creates isolated tests with AAA pattern, proper naming, attributes, and one behavior per test. Supports Value Objects, Entities, Services.

acc-create-test-double

181
from majiayu000/claude-skill-registry

Generates test doubles (Mocks, Stubs, Fakes, Spies) for PHP 8.5. Creates appropriate double type based on testing needs with PHPUnit MockBuilder patterns.

acc-create-test-builder

181
from majiayu000/claude-skill-registry

Generates Test Data Builder and Object Mother patterns for PHP 8.5. Creates fluent builders with sensible defaults and factory methods for test data creation.

acc-create-strategy

181
from majiayu000/claude-skill-registry

Generates Strategy pattern for PHP 8.5. Creates interchangeable algorithm families with context class, strategy interface, and concrete implementations. Includes unit tests.

acc-create-state

181
from majiayu000/claude-skill-registry

Generates State pattern for PHP 8.5. Creates state machines with context, state interface, and concrete states for behavior changes. Includes unit tests.

acc-create-specification

181
from majiayu000/claude-skill-registry

Generates DDD Specification for PHP 8.5. Creates reusable business rule objects for validation, filtering, and querying with composite pattern support. Includes unit tests.

acc-create-saga-pattern

181
from majiayu000/claude-skill-registry

Generates Saga pattern components for PHP 8.5. Creates Saga interfaces, steps, orchestrator, state management, and compensation logic with unit tests.

acc-create-retry-pattern

181
from majiayu000/claude-skill-registry

Generates Retry pattern for PHP 8.5. Creates resilience component with exponential backoff, jitter, and configurable retry strategies. Includes unit tests.

acc-create-responder

181
from majiayu000/claude-skill-registry

Generates ADR Responder classes for PHP 8.5. Creates HTTP response builders with PSR-7/PSR-17 support. Includes unit tests.

acc-create-repository

181
from majiayu000/claude-skill-registry

Generates DDD Repository interfaces and implementation stubs for PHP 8.5. Creates domain interfaces in Domain layer, implementation in Infrastructure.