acc-create-psr11-container

Generates PSR-11 Container implementation for PHP 8.5. Creates ContainerInterface with service resolution, autowiring support, and exceptions. Includes unit tests.

181 stars

Best use case

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

Generates PSR-11 Container implementation for PHP 8.5. Creates ContainerInterface with service resolution, autowiring support, and exceptions. Includes unit tests.

Teams using acc-create-psr11-container 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-psr11-container/SKILL.md --create-dirs "https://raw.githubusercontent.com/majiayu000/claude-skill-registry/main/skills/data/acc-create-psr11-container/SKILL.md"

Manual Installation

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

How acc-create-psr11-container Compares

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

Frequently Asked Questions

What does this skill do?

Generates PSR-11 Container implementation for PHP 8.5. Creates ContainerInterface with service resolution, autowiring support, and exceptions. 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-11 Container Generator

## Overview

Generates PSR-11 compliant dependency injection container implementations.

## When to Use

- Building lightweight DI container
- Creating service locator
- Simple service resolution needs
- Testing with mock containers

## Generated Components

| Component | Description | Location |
|-----------|-------------|----------|
| Container | Container implementation | `src/Infrastructure/Container/` |
| Exceptions | PSR-11 exceptions | `src/Infrastructure/Container/` |
| Unit Tests | PHPUnit tests | `tests/Unit/Infrastructure/Container/` |

## Template: Simple Container

```php
<?php

declare(strict_types=1);

namespace App\Infrastructure\Container;

use Closure;
use Psr\Container\ContainerInterface;

final class Container implements ContainerInterface
{
    /** @var array<string, mixed> */
    private array $services = [];

    /** @var array<string, Closure> */
    private array $factories = [];

    public function get(string $id): mixed
    {
        if (isset($this->services[$id])) {
            return $this->services[$id];
        }

        if (isset($this->factories[$id])) {
            $this->services[$id] = ($this->factories[$id])($this);

            return $this->services[$id];
        }

        throw new NotFoundException("Service not found: {$id}");
    }

    public function has(string $id): bool
    {
        return isset($this->services[$id]) || isset($this->factories[$id]);
    }

    public function set(string $id, mixed $service): void
    {
        $this->services[$id] = $service;
    }

    public function factory(string $id, Closure $factory): void
    {
        $this->factories[$id] = $factory;
    }
}
```

## Template: Autowiring Container

```php
<?php

declare(strict_types=1);

namespace App\Infrastructure\Container;

use Closure;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;

final class AutowiringContainer implements ContainerInterface
{
    /** @var array<string, mixed> */
    private array $services = [];

    /** @var array<string, Closure> */
    private array $factories = [];

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

    public function get(string $id): mixed
    {
        $id = $this->resolveAlias($id);

        if (isset($this->services[$id])) {
            return $this->services[$id];
        }

        if (isset($this->factories[$id])) {
            $this->services[$id] = ($this->factories[$id])($this);

            return $this->services[$id];
        }

        if (class_exists($id)) {
            $this->services[$id] = $this->autowire($id);

            return $this->services[$id];
        }

        throw new NotFoundException("Service not found: {$id}");
    }

    public function has(string $id): bool
    {
        $id = $this->resolveAlias($id);

        return isset($this->services[$id])
            || isset($this->factories[$id])
            || class_exists($id);
    }

    public function set(string $id, mixed $service): void
    {
        $this->services[$id] = $service;
    }

    public function factory(string $id, Closure $factory): void
    {
        $this->factories[$id] = $factory;
    }

    public function alias(string $alias, string $id): void
    {
        $this->aliases[$alias] = $id;
    }

    private function resolveAlias(string $id): string
    {
        return $this->aliases[$id] ?? $id;
    }

    private function autowire(string $class): object
    {
        $reflection = new ReflectionClass($class);

        if (!$reflection->isInstantiable()) {
            throw new ContainerException("Cannot instantiate: {$class}");
        }

        $constructor = $reflection->getConstructor();

        if ($constructor === null) {
            return new $class();
        }

        $parameters = $constructor->getParameters();
        $dependencies = array_map(
            fn(ReflectionParameter $param) => $this->resolveDependency($param),
            $parameters,
        );

        return new $class(...$dependencies);
    }

    private function resolveDependency(ReflectionParameter $parameter): mixed
    {
        $type = $parameter->getType();

        if ($type === null) {
            if ($parameter->isDefaultValueAvailable()) {
                return $parameter->getDefaultValue();
            }

            throw new ContainerException(
                "Cannot resolve parameter: {$parameter->getName()}",
            );
        }

        if (!$type instanceof ReflectionNamedType || $type->isBuiltin()) {
            if ($parameter->isDefaultValueAvailable()) {
                return $parameter->getDefaultValue();
            }

            throw new ContainerException(
                "Cannot resolve builtin type: {$parameter->getName()}",
            );
        }

        return $this->get($type->getName());
    }
}
```

## Template: Exceptions

```php
<?php

declare(strict_types=1);

namespace App\Infrastructure\Container;

use Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

final class ContainerException extends Exception implements ContainerExceptionInterface
{
}

final class NotFoundException extends Exception implements NotFoundExceptionInterface
{
}
```

## Template: Unit Test

```php
<?php

declare(strict_types=1);

namespace App\Tests\Unit\Infrastructure\Container;

use App\Infrastructure\Container\AutowiringContainer;
use App\Infrastructure\Container\NotFoundException;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

#[Group('unit')]
#[CoversClass(AutowiringContainer::class)]
final class AutowiringContainerTest extends TestCase
{
    private AutowiringContainer $container;

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

    #[Test]
    public function it_resolves_registered_service(): void
    {
        $service = new \stdClass();
        $this->container->set('service', $service);

        self::assertSame($service, $this->container->get('service'));
    }

    #[Test]
    public function it_resolves_factory(): void
    {
        $this->container->factory('service', fn() => new \stdClass());

        $service1 = $this->container->get('service');
        $service2 = $this->container->get('service');

        self::assertSame($service1, $service2);
    }

    #[Test]
    public function it_autowires_class(): void
    {
        $service = $this->container->get(SimpleService::class);

        self::assertInstanceOf(SimpleService::class, $service);
    }

    #[Test]
    public function it_throws_not_found_for_unknown_service(): void
    {
        $this->expectException(NotFoundException::class);

        $this->container->get('unknown');
    }

    #[Test]
    public function it_resolves_aliases(): void
    {
        $this->container->set('concrete', new \stdClass());
        $this->container->alias('alias', 'concrete');

        self::assertSame(
            $this->container->get('concrete'),
            $this->container->get('alias'),
        );
    }
}

class SimpleService
{
}
```

## Usage Example

```php
<?php

use App\Infrastructure\Container\AutowiringContainer;

$container = new AutowiringContainer();

// Register services
$container->set('config', ['db' => 'mysql://localhost/app']);

// Register factories
$container->factory(LoggerInterface::class, fn($c) => new FileLogger('/var/log/app.log'));

// Register aliases (interface to implementation)
$container->alias(UserRepositoryInterface::class, DoctrineUserRepository::class);

// Resolve services
$logger = $container->get(LoggerInterface::class);
$repository = $container->get(UserRepositoryInterface::class);
$handler = $container->get(CreateUserHandler::class); // Autowired
```

## Requirements

```json
{
    "require": {
        "psr/container": "^2.0"
    }
}
```

## See Also

- `references/templates.md` - Additional container patterns
- `references/examples.md` - Integration examples

Related Skills

Advanced Deterministic Runtime Container

181
from majiayu000/claude-skill-registry

Build deterministic IoC containers with proper lifecycle management, scoping, and disposal patterns. Use when implementing DI containers, managing service lifetimes, or designing runtime systems.

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.