waffle-commons / container
Container component for Waffle framework.
Requires
- php: ^8.5
- psr/container: ^2.0
- waffle-commons/contracts: 0.1.0-beta2.1
Requires (Dev)
- carthage-software/mago: ^1.29
- cyclonedx/cyclonedx-php-composer: ^6.2
- php-mock/php-mock-phpunit: ^2.15
- phpunit/phpunit: ^12.5
- vimeo/psalm: ^6.16
This package is auto-updated.
Last update: 2026-05-30 19:46:45 UTC
README
Waffle Container Component
Release:
v0.1.0-beta2ย |ยCHANGELOG.mdPSR Compliance: PSR-11 (Psr\Container\ContainerInterface)
A strict PSR-11 service container with reflection-based autowiring, circular-dependency detection, and worker-mode resettability. Core services (the PSR-11 ContainerInterface itself) are locked from override after registration.
๐ฆ Installation
composer require waffle-commons/container
๐งฑ Surface
| Class | Role |
|---|---|
Waffle\Commons\Container\Container |
The container. Implements Waffle\Commons\Contracts\Container\ContainerInterface (PSR-11 + ResettableInterface). |
Waffle\Commons\Container\Autowire |
Reflection-based autowiring helper used by Container::build() to resolve constructor parameters. |
Waffle\Commons\Container\Exception\ContainerException |
Thrown for retrieval / resolution failures. |
Waffle\Commons\Container\Exception\NotFoundException |
Thrown when get($id) cannot resolve the identifier. |
๐ Usage
use Waffle\Commons\Container\Container; $container = new Container([ // Direct instance LoggerInterface::class => new StreamLogger(), // Class string โ autowired via reflection on first get() UserService::class => UserService::class, // Factory closure 'app.config' => static fn() => new Config(__DIR__ . '/config', 'prod'), ]); $logger = $container->get(LoggerInterface::class); $exists = $container->has(UserService::class); $container->set('db.cache', new ArrayCache());
The exact public signature, verbatim from Waffle\Commons\Contracts\Container\ContainerInterface:
public function get(string $id): mixed; public function has(string $id): bool; public function set(string $id, object|callable|string $concrete): void; public function reset(): void; // from ResettableInterface
๐ Worker-mode reset
Container implements ResettableInterface. After each request, the kernel calls reset() so the container drops its instance cache while keeping the registered definitions, preventing user-context leaks across FrankenPHP worker requests.
๐ก๏ธ Locked core services
The constant Container::CORE_SERVICES lists identifiers that must not be redefined once registered. The PSR-11 ContainerInterface itself is in that list โ any attempt to override it after the container is built throws ContainerException.
๐ Circular-dependency detection
Container::get($id) tracks the resolution stack in $resolving and throws ContainerException if a cycle is detected before infinite recursion can occur.
๐ PHP 8.5 features used
final class Containerโ no subclassing.- Typed properties throughout.
- Typed constants for service registries:
private const CORE_SERVICES = [...];. #[\Override]on every method that overrides PSR-11.
๐งญ Architectural boundary (mago guard)
An active dependency perimeter is enforced on every CI run by vendor/bin/mago guard (bundled into composer mago; zero baselines). The rules live in mago.toml under [guard.perimeter] โ a forbidden use statement fails the build, not a reviewer.
Production code under Waffle\Commons\Container may depend only on:
Waffle\Commons\Container\**โ itselfWaffle\Commons\Contracts\**โ the shared contracts package, the only Waffle dependency permittedPsr\**โ PSR interfaces (PSR-11)@global+Psl\**โ PHP core and the PHP Standard Library
Test code under WaffleTests\Commons\Container is unrestricted (@all). Structural rules are guarded too: interfaces must be named *Interface, Exception\** classes must end in *Exception, and any Enum\** namespace may hold only enum declarations.
Contract-first, component-agnostic by construction: components compose through waffle-commons/contracts, never directly through one another.
๐งช Testing
docker exec -w /waffle-commons/container waffle-dev composer tests
๐ License
MIT โ see LICENSE.md.