Writing PHP container from scratch - solving class duplicate dependency creation

(3) Writing PHP container from scratch - solving class duplicate dependency creation

Function realization

  • Solve class duplicate dependency creation, solve interdependence (a - > b - > A - > b - > etc.), circular dependency (a - > b - > C - > A - > b - > C - > A - > A - > b - > C - > A - > A - > etc.)

code implementation Container

    /**
     * Resolve interdependence and circular dependency judgment
     * @param string $abstract
     * @param array $tmp
     * @return Closure|object
     * @throws ReflectionException
     */
    public function createObjectNoEach(string $abstract, array $tmp = [])
    {
        if ($tmpInstance = &$tmp[$abstract]) {
            return $tmpInstance;
        }
        $refClass = new ReflectionClass($abstract);
        if ($refClass->getName() === Closure::class) {
            return function (){};
        } elseif ($refClass->hasMethod('__construct')) {
            $_constructParams = array_map(function (ReflectionParameter $param) use ($abstract, $tmp) {
                if ($param->getClass()) {
                    if (array_key_exists($param->getClass()->getName(), $tmp)) {
                        throw new class('can not create a circular dependencies class object.') extends Exception implements ContainerExceptionInterface{ };
                    }
                    return $this->createObjectNoEach($param->getClass()->getName(), $tmp);
                } elseif ($param->isDefaultValueAvailable()) {
                    return $param->getDefaultValue();
                } elseif ($param->getType()) {
                    return [
                            'string' => '',
                            'int' => 0,
                            'array' => [],
                            'bool' => false,
                            'float' => 0.0,
                            'iterable' => [],
                            'callable' => function() {}
                        ][$param->getType()->getName()] ?? null;
                } else {
                    return null;
                }
            }, $refClass->getMethod('__construct')->getParameters());
        }
        return $tmpInstance = $refClass->newInstance(... ($_constructParams ?? []));
    }

Implementation ideas

  • Automatically create an instance object through storage, judge it as a loop when the same class appears in the parameter list and throw an exception

Add code

  1. Determine whether the instance object is cached
if ($tmpInstance = &$tmp[$abstract]) {
    return $tmpInstance;
}
  1. Determine whether the automatically created class has been created. If it has been created, it will be considered as recursion and an exception will be thrown
if (array_key_exists($param->getClass()->getName(), $tmp)) {
    throw new class('can not create a circular dependencies class object.') extends Exception implements ContainerExceptionInterface{ };
}
return $this->createObjectNoEach($param->getClass()->getName(), $tmp);
  1. Store automatically created class instances
return $tmpInstance = $refClass->newInstance(... ($_constructParams ?? []));

notes

Example

Keywords: Programming PHP

Added by wopopd83 on Wed, 19 Feb 2020 18:13:10 +0200