25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.1KB

  1. <?php
  2. namespace Framework;
  3. use InvalidArgumentException;
  4. use ReflectionFunction;
  5. use ReflectionMethod;
  6. use ReflectionNamedType;
  7. class Container
  8. {
  9. private array $bindings = [];
  10. private array $resolved = [];
  11. public function bind(string $alias, callable $factory): static
  12. {
  13. $this->bindings[$alias] = $factory;
  14. $this->resolved[$alias] = null;
  15. return $this;
  16. }
  17. public function resolve(string $alias): mixed
  18. {
  19. if (!isset($this->bindings[$alias])) {
  20. throw new InvalidArgumentException("{$alias} is not bound");
  21. }
  22. if (!isset($this->resolved[$alias])) {
  23. $this->resolved[$alias] = call_user_func($this->bindings[$alias], $this);
  24. }
  25. return $this->resolved[$alias];
  26. }
  27. public function has(string $alias): bool
  28. {
  29. return isset($this->bindings[$alias]);
  30. }
  31. public function call(array|callable $callable, array $parameters = []): mixed
  32. {
  33. $reflector = $this->getReflector($callable);
  34. $dependencies = [];
  35. foreach ($reflector->getParameters() as $parameter) {
  36. $name = $parameter->getName();
  37. $type = $parameter->getType();
  38. if (isset($parameters[$name])) {
  39. $dependencies[$name] = $parameters[$name];
  40. continue;
  41. }
  42. if ($parameter->isDefaultValueAvailable()) {
  43. $dependencies[$name] = $parameter->getDefaultValue();
  44. continue;
  45. }
  46. if ($type instanceof ReflectionNamedType) {
  47. $dependencies[$name] = $this->resolve($type);
  48. continue;
  49. }
  50. throw new InvalidArgumentException("{$name} cannot be resolved");
  51. }
  52. return call_user_func($callable, ...array_values($dependencies));
  53. }
  54. private function getReflector(array|callable $callable): ReflectionMethod|ReflectionFunction
  55. {
  56. if (is_array($callable)) {
  57. return new ReflectionMethod($callable[0], $callable[1]);
  58. }
  59. return new ReflectionFunction($callable);
  60. }
  61. }

Powered by TurnKey Linux.