Files
spa-api/laravel/ioc.php

208 lines
5.5 KiB
PHP
Raw Normal View History

2012-01-16 13:59:24 -06:00
<?php namespace Laravel; use Closure;
class IoC {
/**
* The registered dependencies.
*
* @var array
*/
2012-01-16 13:59:24 -06:00
public static $registry = array();
/**
* The resolved singleton instances.
*
* @var array
*/
2012-01-16 13:59:24 -06:00
public static $singletons = array();
2011-08-26 21:42:04 -05:00
/**
2011-09-16 20:30:22 -05:00
* Register an object and its resolver.
*
* @param string $name
* @param mixed $resolver
2012-02-04 21:30:52 +00:00
* @param bool $singleton
* @return void
*/
2012-05-02 13:39:59 -05:00
public static function register($name, $resolver = null, $singleton = false)
{
2012-05-02 13:39:59 -05:00
if (is_null($resolver)) $resolver = $name;
2012-01-16 13:59:24 -06:00
static::$registry[$name] = compact('resolver', 'singleton');
}
/**
2011-09-16 20:30:22 -05:00
* Determine if an object has been registered in the container.
*
* @param string $name
* @return bool
*/
public static function registered($name)
{
return array_key_exists($name, static::$registry);
}
/**
2011-09-16 20:30:22 -05:00
* Register an object as a singleton.
*
2011-09-21 21:46:16 -05:00
* Singletons will only be instantiated the first time they are resolved.
2011-09-08 17:49:16 -05:00
*
* @param string $name
* @param Closure $resolver
* @return void
*/
2012-05-02 13:39:59 -05:00
public static function singleton($name, $resolver = null)
{
static::register($name, $resolver, true);
}
/**
2012-01-16 13:59:24 -06:00
* Register an existing instance as a singleton.
2011-09-08 17:49:16 -05:00
*
2011-09-21 22:39:02 -05:00
* <code>
* // Register an instance as a singleton in the container
2011-11-11 09:52:30 +00:00
* IoC::instance('mailer', new Mailer);
2011-09-21 22:39:02 -05:00
* </code>
*
* @param string $name
* @param mixed $instance
* @return void
*/
public static function instance($name, $instance)
{
static::$singletons[$name] = $instance;
}
/**
* Resolve a given type to an instance.
2011-09-27 21:10:32 -05:00
*
* <code>
* // Get an instance of the "mailer" object registered in the container
* $mailer = IoC::resolve('mailer');
2011-09-27 21:10:32 -05:00
*
* // Get an instance of the "mailer" object and pass parameters to the resolver
* $mailer = IoC::resolve('mailer', array('test'));
2011-09-27 21:10:32 -05:00
* </code>
*
* @param string $type
2012-08-03 18:17:48 +03:00
* @param array $parameters
2011-09-27 21:10:32 -05:00
* @return mixed
*/
public static function resolve($type, $parameters = array())
2011-09-27 21:10:32 -05:00
{
// If an instance of the type is currently being managed as a singleton, we will
// just return the existing instance instead of instantiating a fresh instance
// so the developer can keep re-using the exact same object instance from us.
if (isset(static::$singletons[$type]))
{
return static::$singletons[$type];
}
2012-05-02 16:49:48 -05:00
// If we don't have a registered resolver or concrete for the type, we'll just
// assume the type is the concrete name and will attempt to resolve it as is
// since the container should be able to resolve concretes automatically.
if ( ! isset(static::$registry[$type]))
{
$concrete = $type;
}
else
{
$concrete = array_get(static::$registry[$type], 'resolver', $type);
}
// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the type, as well as resolve any of
// its nested dependencies recursively until they are each resolved.
if ($concrete == $type or $concrete instanceof Closure)
{
$object = static::build($concrete, $parameters);
}
else
{
$object = static::resolve($concrete);
}
// If the requested type is registered as a singleton, we want to cache off
// the instance in memory so we can return it later without creating an
// entirely new instances of the object on each subsequent request.
if (isset(static::$registry[$type]['singleton']) && static::$registry[$type]['singleton'] === true)
{
static::$singletons[$type] = $object;
}
2012-06-13 10:25:14 -05:00
Event::fire('laravel.resolving', array($type, $object));
return $object;
2011-09-27 21:10:32 -05:00
}
/**
* Instantiate an instance of the given type.
*
* @param string $type
2011-10-05 18:32:48 -05:00
* @param array $parameters
* @return mixed
*/
protected static function build($type, $parameters = array())
{
// If the concrete type is actually a Closure, we will just execute it and
// hand back the results of the function, which allows functions to be
// used as resolvers for more fine-tuned resolution of the objects.
if ($type instanceof Closure)
{
return call_user_func_array($type, $parameters);
}
$reflector = new \ReflectionClass($type);
// If the type is not instantiable, the developer is attempting to resolve
// an abstract type such as an Interface of an Abstract Class and there is
// no binding registered for the abstraction so we need to bail out.
if ( ! $reflector->isInstantiable())
{
throw new \Exception("Resolution target [$type] is not instantiable.");
}
$constructor = $reflector->getConstructor();
// If there is no constructor, that means there are no dependencies and
// we can just resolve an instance of the object right away without
// resolving any other types or dependencies from the container.
if (is_null($constructor))
{
return new $type;
}
$dependencies = static::dependencies($constructor->getParameters());
return $reflector->newInstanceArgs($dependencies);
}
/**
* Resolve all of the dependencies from the ReflectionParameters.
*
2012-07-24 09:31:27 +00:00
* @param array $parameters
* @return array
*/
protected static function dependencies($parameters)
{
$dependencies = array();
foreach ($parameters as $parameter)
{
$dependency = $parameter->getClass();
// If the class is null, it means the dependency is a string or some other
// primitive type, which we can not resolve since it is not a class and
// we'll just bomb out with an error since we have nowhere to go.
if (is_null($dependency))
{
throw new \Exception("Unresolvable dependency resolving [$parameter].");
}
$dependencies[] = static::resolve($dependency->name);
}
return (array) $dependencies;
}
2012-01-16 13:59:24 -06:00
}