123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- <?php
- declare(strict_types=1);
- /**
- * This file is part of Hyperf.
- *
- * @link https://www.hyperf.io
- * @document https://hyperf.wiki
- * @contact group@hyperf.io
- * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
- */
- namespace Hyperf\Pimple;
- use Hyperf\Contract\ContainerInterface;
- use Hyperf\Pimple\Exception\InvalidDefinitionException;
- use Hyperf\Pimple\Exception\NotFoundException;
- use Hyperf\Pimple\Exception\NotSupportException;
- use Pimple;
- use Psr\Container\ContainerInterface as PsrContainerInterface;
- use ReflectionClass;
- use ReflectionException;
- use ReflectionMethod;
- use ReflectionParameter;
- class Container implements ContainerInterface
- {
- /**
- * @var Pimple\Container
- */
- protected $pimple;
- /**
- * @var ReflectionClass[]
- */
- protected $reflection = [];
- public function __construct(Pimple\Container $pimple)
- {
- $this->pimple = $pimple;
- $this->pimple[ContainerInterface::class] = $this;
- $this->pimple[PsrContainerInterface::class] = $this;
- }
- public function get($id)
- {
- if ($this->has($id)) {
- return $this->pimple[$id];
- }
- return $this->pimple[$id] = $this->make($id);
- }
- public function has($id): bool
- {
- return isset($this->pimple[$id]);
- }
- public function make(string $name, array $parameters = [])
- {
- if (! class_exists($name)) {
- throw new NotFoundException("Entry {$name} is not found.");
- }
- $ref = $this->reflection[$name] ?? new ReflectionClass($name);
- $constructor = $ref->getConstructor();
- $args = [];
- if ($constructor && $constructor->isPublic()) {
- $args = $this->resolveParameters($constructor, $parameters);
- }
- $instance = new $name(...$args);
- $this->reflection[$name] = $ref;
- return $instance;
- }
- public function set(string $name, $entry): void
- {
- $this->pimple[$name] = $entry;
- }
- public function define(string $name, $definition): void
- {
- throw new NotSupportException('Method define is not support.');
- }
- public function unbind(string $name): void
- {
- $this->pimple[$name] = null;
- }
- protected function resolveParameters(ReflectionMethod $method, $parameters = [])
- {
- $args = [];
- foreach ($method->getParameters() as $index => $parameter) {
- if (array_key_exists($parameter->getName(), $parameters)) {
- $value = $parameters[$parameter->getName()];
- } elseif (array_key_exists($index, $parameters)) {
- $value = $parameters[$index];
- } elseif ($parameter->getType() && $this->has($parameter->getType()->getName())) {
- $value = $this->get($parameter->getType()->getName());
- } else {
- if ($parameter->isDefaultValueAvailable() || $parameter->isOptional()) {
- $value = $this->getParameterDefaultValue($parameter, $method);
- } else {
- throw new InvalidDefinitionException(sprintf(
- 'Parameter $%s of %s has no value defined or guessable',
- $parameter->getName(),
- $this->getFunctionName($method)
- ));
- }
- }
- $args[] = $value;
- }
- return $args;
- }
- protected function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function)
- {
- try {
- return $parameter->getDefaultValue();
- } catch (ReflectionException $e) {
- throw new InvalidDefinitionException(sprintf(
- 'The parameter "%s" of %s has no type defined or guessable. It has a default value, '
- . 'but the default value can\'t be read through Reflection because it is a PHP internal class.',
- $parameter->getName(),
- $this->getFunctionName($function)
- ));
- }
- }
- private function getFunctionName(ReflectionMethod $method): string
- {
- return $method->getName() . '()';
- }
- }
|