services[$name] = $factory; } /** * Register a singleton service */ public function singleton(string $name, callable $factory): void { $this->singletons[$name] = $factory; } /** * Get a service instance */ public function get(string $name) { // Check singletons first if (isset($this->singletons[$name])) { if (!isset($this->services[$name])) { $this->services[$name] = $this->singletons[$name](); } return $this->services[$name]; } // Check regular services if (isset($this->services[$name])) { if (is_callable($this->services[$name])) { return $this->services[$name](); } return $this->services[$name]; } // Try to auto-resolve if (class_exists($name)) { return $this->resolve($name); } throw new \Exception("Service '{$name}' not found in container"); } /** * Auto-resolve class dependencies */ public function resolve(string $className) { $reflection = new \ReflectionClass($className); if (!$reflection->isInstantiable()) { throw new \Exception("Class '{$className}' is not instantiable"); } $constructor = $reflection->getConstructor(); if (!$constructor) { return new $className(); } $parameters = $constructor->getParameters(); $dependencies = []; foreach ($parameters as $parameter) { $type = $parameter->getType(); if ($type && !$type->isBuiltin()) { $dependencies[] = $this->resolve($type->getName()); } elseif ($parameter->isDefaultValueAvailable()) { $dependencies[] = $parameter->getDefaultValue(); } else { throw new \Exception("Cannot resolve parameter '{$parameter->getName()}' for class '{$className}'"); } } return $reflection->newInstanceArgs($dependencies); } /** * Inject dependencies into an object */ public function inject(object $object): void { $reflection = new \ReflectionClass($object); $properties = $reflection->getProperties(); foreach ($properties as $property) { if ($property->isPublic() && !$property->isInitialized($object)) { $type = $property->getType(); if ($type && !$type->isBuiltin()) { $property->setValue($object, $this->get($type->getName())); } } } } /** * Check if service exists */ public function has(string $name): bool { return isset($this->services[$name]) || isset($this->singletons[$name]); } /** * Get all services */ public function getServices(): array { return array_merge($this->services, $this->singletons); } }