diff --git a/Container.php b/Container.php index 8f620d5..66061c9 100644 --- a/Container.php +++ b/Container.php @@ -72,6 +72,7 @@ class Container implements ContainerInterface * @param string $id * @return mixed * @throws ReflectionException + * @throws \Exception */ public function get(string $id): mixed { @@ -83,6 +84,9 @@ class Container implements ContainerInterface $id = $this->_interfaces[$id]; } $this->_singletons[$id] = $this->make($id); + if (!$this->_singletons[$id]) { + throw new \Exception('Class that cannot be instantiated。'); + } } return $this->_singletons[$id]; } @@ -126,16 +130,19 @@ class Container implements ContainerInterface /** * @param string $className - * @return ReflectionClass + * @return ReflectionClass|null * @throws ReflectionException */ - public function getReflectionClass(string $className): ReflectionClass + public function getReflectionClass(string $className): ?ReflectionClass { if (isset($this->_reflection[$className])) { return $this->_reflection[$className]; } $class = new ReflectionClass($className); + if (!$class->isInstantiable()) { + return null; + } return $this->_reflection[$className] = $class; } @@ -145,12 +152,14 @@ class Container implements ContainerInterface * @param string $className * @param array $construct * @param array $config - * @return object + * @return object|null * @throws ReflectionException */ - public function make(string $className, array $construct = [], array $config = []): object + public function make(string $className, array $construct = [], array $config = []): ?object { - $reflect = $this->getReflectionClass($className); + if (($reflect = $this->getReflectionClass($className)) === null) { + return null; + } $constructorHandler = $reflect->getConstructor(); if (count($construct) < 1 && $constructorHandler !== null) { diff --git a/Scanner.php b/Scanner.php new file mode 100644 index 0000000..f57aa03 --- /dev/null +++ b/Scanner.php @@ -0,0 +1,103 @@ +load_dir($path); + } + + + /** + * @param string $namespace + * @return void + * @throws ReflectionException + * @throws Exception + */ + public function parse(string $namespace): void + { + $container = Container::instance(); + foreach ($this->files as $file) { + $class = $namespace . '\\' . $this->rename($file); + if (file_exists($class)) { + error('Please follow the PSR-4 specification to write code.' . $class); + continue; + } + $container->parse($class); + } + } + + + /** + * @param string $file + * @return string + */ + private function rename(string $file): string + { + $filter = array_filter(explode('/', $file), function ($value) { + if (empty($value)) { + return false; + } + return ucfirst($value); + }); + array_shift($filter); + return implode('\\', $filter); + } + + + /** + * @param string $path + * @return void + */ + private function load_dir(string $path): void + { + $dir = new \DirectoryIterator($path); + foreach ($dir as $value) { + if ($value->isDot()) { + continue; + } + if ($value->isDir()) { + $this->load_dir($value->getRealPath()); + } else if ($value->getExtension() == '.php') { + $this->load_file($value); + } + } + } + + + /** + * @param string $path + * @return void + */ + private function load_file(string $path): void + { + try { + require_once "$path"; + $path = str_replace($_SERVER['HOME'], '', $path); + $path = str_replace('.php', '', $path); + $this->files[] = $path; + } catch (\Throwable $throwable) { + error($throwable->getMessage(), [$throwable]); + } + } + + +}