Container.php
- Pfad:
src/Framework/Container.php - Namespace: Framework
- Zeilen: 176 | Größe: 5,172 Bytes
- Geändert: 2025-12-23 08:09:01 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 100
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 3
- use ReflectionClass
- use ReflectionNamedType
- use ReflectionParameter
Klassen 1
-
Containerclass Zeile 13
Funktionen 6
-
set()public Zeile 27 -
instance()public Zeile 40 -
has()public Zeile 48 -
get()public Zeile 65 -
autowire()Zeile 95 -
resolveParameter()Zeile 125
Verwendet von 6
- ChatServiceProvider.php use
- ContentServiceProvider.php use
- InfrastructureServiceProvider.php use
- ServiceProviderInterface.php use
- services.php use
- TaskServiceProvider.php use
Versionen 3
-
v3
2025-12-23 08:09 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-22 15:32 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-22 15:31 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
Code
<?php
declare(strict_types=1);
namespace Framework;
// @responsibility: DI-Container mit Autowiring und Singleton-Caching
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;
final class Container
{
/** @var array<string, object> Cached singleton instances */
private array $instances = [];
/** @var array<string, callable> Factory functions */
private array $factories = [];
/**
* Register a factory for a service.
*
* @param string $id Service identifier (usually class name)
* @param callable(Container): object $factory Factory function
*/
public function set(string $id, callable $factory): void
{
$this->factories[$id] = $factory;
// Clear cached instance if re-registering
unset($this->instances[$id]);
}
/**
* Register an existing instance as a singleton.
*
* @param string $id Service identifier
* @param object $instance The instance to register
*/
public function instance(string $id, object $instance): void
{
$this->instances[$id] = $instance;
}
/**
* Check if a service is registered.
*/
public function has(string $id): bool
{
return isset($this->instances[$id]) || isset($this->factories[$id]) || class_exists($id);
}
/**
* Get a service by ID.
*
* Resolution order:
* 1. Check cached instances
* 2. Check registered factories
* 3. Try autowiring if ID is a class name
*
* @param string $id Service identifier (usually class name)
* @return object The resolved service instance
* @throws ContainerException If service cannot be resolved
*/
public function get(string $id): object
{
// Return cached instance if available
if (isset($this->instances[$id])) {
return $this->instances[$id];
}
// Use factory if registered
if (isset($this->factories[$id])) {
$this->instances[$id] = ($this->factories[$id])($this);
return $this->instances[$id];
}
// Try autowiring for class names
if (class_exists($id)) {
$this->instances[$id] = $this->autowire($id);
return $this->instances[$id];
}
throw new ContainerException("Service not found: {$id}");
}
/**
* Autowire a class by resolving constructor dependencies.
*
* @param class-string $class
* @throws ContainerException
*/
private function autowire(string $class): object
{
$reflection = new ReflectionClass($class);
if (!$reflection->isInstantiable()) {
throw new ContainerException("Cannot instantiate {$class}");
}
$constructor = $reflection->getConstructor();
// No constructor = no dependencies
if ($constructor === null) {
return new $class();
}
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $param) {
$dependencies[] = $this->resolveParameter($param, $class);
}
return $reflection->newInstanceArgs($dependencies);
}
/**
* Resolve a single constructor parameter.
*
* @throws ContainerException
*/
private function resolveParameter(ReflectionParameter $param, string $class): mixed
{
$type = $param->getType();
// Handle nullable/optional parameters with default values
if ($param->isDefaultValueAvailable()) {
// Try to resolve the type, but fall back to default if it fails
if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
$typeName = $type->getName();
// Only try to resolve if explicitly registered (not just class_exists)
if (isset($this->instances[$typeName]) || isset($this->factories[$typeName])) {
try {
return $this->get($typeName);
} catch (ContainerException) {
// Fall through to default value
}
}
}
return $param->getDefaultValue();
}
// No type hint
if ($type === null) {
throw new ContainerException(
"Cannot resolve parameter \${$param->getName()} in {$class}: no type hint"
);
}
// Union types not supported
if (!$type instanceof ReflectionNamedType) {
throw new ContainerException(
"Cannot resolve parameter \${$param->getName()} in {$class}: union types not supported"
);
}
// Built-in types (string, int, etc.) cannot be autowired
if ($type->isBuiltin()) {
if ($type->allowsNull()) {
return null;
}
throw new ContainerException(
"Cannot resolve parameter \${$param->getName()} in {$class}: built-in type {$type->getName()}"
);
}
// Resolve the dependency
return $this->get($type->getName());
}
}