Skip to content

Instantly share code, notes, and snippets.

@swport
Last active October 24, 2018 08:41
Show Gist options
  • Save swport/8ba2dacca8dc41d462cd4fd40f822b52 to your computer and use it in GitHub Desktop.
Save swport/8ba2dacca8dc41d462cd4fd40f822b52 to your computer and use it in GitHub Desktop.
Simple Dependency Resolver in PHP. Dependency Autowiring.
<?php
/*
* USAGE:
*
* // this is where I define all my dependencies in case if they are not directly instantiable (resolvable)
* $deps = array(
* 'DependentClass' => array(
* 'depclass' => 'DependencyClass'
* )
* );
* ObjectManager::getInstance()->setDependencies($deps);
*
* class DependentClass {
* private $depclass;
* private $dep2;
* function __constructor(DependencyClassInterface $depclass, DirectlyResolvableClass $dep2) {
* $this->dep2 = $dep2;
* $this->depclass = $depclass;
* }
* function doSomething() {}
* }
*
* ObjectManager::getInstance()
* ->get('DependentClass')
* ->doSomething();
*
*/
class ObjectManager
{
protected $dependencies;
protected static $omInstance;
public static function getInstance()
{
if (!self::$omInstance) {
self::$omInstance = new ObjectManager();
}
return self::$omInstance;
}
public function setDependencies(array $dependencies)
{
$this->dependencies = $dependencies;
}
public function getDependencies()
{
return $this->dependencies;
}
public function get($class)
{
$finalizedParams = array();
$deps = array();
// check if deps are defined
if (array_key_exists($class, $this->dependencies)) {
$deps = $this->dependencies[$class];
}
$reflector = new ReflectionClass($class);
if (!$reflector->isInstantiable()) {
throw new Exception("Class {$class} is not instantiable");
}
$constructor = $reflector->getConstructor();
if ($constructor == null) {
return $reflector->newInstance();
}
$parameters = $constructor->getParameters();
foreach ($parameters as $key => $parameter) {
$parameterType = $this->getParameterType($parameter);
$parameterName = $parameter->getName();
if ($parameterType == null) {
if ($parameter->isDefaultValueAvailable()) {
$finalizedParams[$key] = $parameter->getDefaultValue();
} else {
throw new Exception("
Failed resolving argument (dependency) \"$parameterName\" for class $class.
Not directly instantiatable.
No default value specified.");
}
continue;
}
$classReflection = new ReflectionClass($parameterType);
// if dep is directly instantiable; save and continue
if ($classReflection->isInstantiable()) {
$finalizedParams[$key] = $classReflection->newInstance();
continue;
}
// if defined in di.php
if (array_key_exists($parameterName, $deps)) {
$argName = $deps[$parameterName];
$finalizedParams[$key] = ObjectManager::getInstance()->get($argName);
continue;
}
}
return $reflector->newInstanceArgs($finalizedParams);
}
protected function getParameterType(ReflectionParameter $parameter)
{
$export = ReflectionParameter::export(
array(
$parameter->getDeclaringClass()->name,
$parameter->getDeclaringFunction()->name,
),
$parameter->name,
true
);
return preg_match('/[>] ([A-z]+) /', $export, $matches)
? $matches[1] : null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment