Skip to content

Instantly share code, notes, and snippets.

@MustafaMagdi
Forked from tlikai/container.php
Last active April 17, 2024 19:14
Show Gist options
  • Save MustafaMagdi/2bb27aebf6ab078b1f3e5635c0282fac to your computer and use it in GitHub Desktop.
Save MustafaMagdi/2bb27aebf6ab078b1f3e5635c0282fac to your computer and use it in GitHub Desktop.
PHP Dependency Injection Container
<?php
/**
* Class Container
*/
class Container
{
/**
* @var array
*/
protected $instances = [];
/**
* @param $abstract
* @param null $concrete
*/
public function set($abstract, $concrete = NULL)
{
if ($concrete === NULL) {
$concrete = $abstract;
}
$this->instances[$abstract] = $concrete;
}
/**
* @param $abstract
* @param array $parameters
*
* @return mixed|null|object
* @throws Exception
*/
public function get($abstract, $parameters = [])
{
// if we don't have it, just register it
if (!isset($this->instances[$abstract])) {
$this->set($abstract);
}
return $this->resolve($this->instances[$abstract], $parameters);
}
/**
* resolve single
*
* @param $concrete
* @param $parameters
*
* @return mixed|object
* @throws Exception
*/
public function resolve($concrete, $parameters)
{
if ($concrete instanceof Closure) {
return $concrete($this, $parameters);
}
$reflector = new ReflectionClass($concrete);
// check if class is instantiable
if (!$reflector->isInstantiable()) {
throw new Exception("Class {$concrete} is not instantiable");
}
// get class constructor
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
// get new instance from class
return $reflector->newInstance();
}
// get constructor params
$parameters = $constructor->getParameters();
$dependencies = $this->getDependencies($parameters);
// get new instance with dependencies resolved
return $reflector->newInstanceArgs($dependencies);
}
/**
* get all dependencies resolved
*
* @param $parameters
*
* @return array
* @throws Exception
*/
public function getDependencies($parameters)
{
$dependencies = [];
foreach ($parameters as $parameter) {
// get the type hinted class
$dependency = $parameter->getClass();
if ($dependency === NULL) {
// check if default value for a parameter is available
if ($parameter->isDefaultValueAvailable()) {
// get default value of parameter
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new Exception("Can not resolve class dependency {$parameter->name}");
}
} else {
// get dependency resolved
$dependencies[] = $this->get($dependency->name);
}
}
return $dependencies;
}
}
@Kriesi
Copy link

Kriesi commented Aug 4, 2023

nice solution, thanks! since

$dependency = $parameter->getClass();

is deprecated in the lastest php version, what would you suggest to fix that? 🤔

@aliyilmazco
Copy link

$dependency = $parameter->getType() && !$parameter->getType()->isBuiltin() ? new \ReflectionClass($parameter->getType()->getName()) : null;
This change fixes the error caused by the Deprecated: Function ReflectionParameter::getClass() is deprecated message after a new PHP update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment