| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 | <?php namespace Laravel; use Closure;class IoC {	/**	 * The registered dependencies.	 *	 * @var array	 */	public static $registry = array();	/**	 * The resolved singleton instances.	 *	 * @var array	 */	public static $singletons = array();	/**	 * Register an object and its resolver.	 *	 * @param  string   $name	 * @param  mixed    $resolver	 * @param  bool     $singleton	 * @return void	 */	public static function register($name, $resolver = null, $singleton = false)	{		if (is_null($resolver)) $resolver = $name;		static::$registry[$name] = compact('resolver', 'singleton');	}    /**     * Unregister an object     *     * @param string $name     */    public static function unregister($name)    {        if (array_key_exists($name, static::$registry)) {            unset(static::$registry[$name]);            unset(static::$singletons[$name]);        }    }	/**	 * 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) || array_key_exists($name, static::$singletons);	}	/**	 * Register an object as a singleton.	 *	 * Singletons will only be instantiated the first time they are resolved.	 *	 * @param  string   $name	 * @param  Closure  $resolver	 * @return void	 */	public static function singleton($name, $resolver = null)	{		static::register($name, $resolver, true);	}	/**	 * Register an existing instance as a singleton.	 *	 * <code>	 *		// Register an instance as a singleton in the container	 *		IoC::instance('mailer', new Mailer);	 * </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.	 *	 * <code>	 *		// Get an instance of the "mailer" object registered in the container	 *		$mailer = IoC::resolve('mailer');	 *	 *		// Get an instance of the "mailer" object and pass parameters to the resolver	 *		$mailer = IoC::resolve('mailer', array('test'));	 * </code>	 *	 * @param  string  $type	 * @param  array   $parameters	 * @return mixed	 */	public static function resolve($type, $parameters = array())	{		// 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];		}		// 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;		}		Event::fire('laravel.resolving', array($type, $object));		return $object;	}	/**	 * Instantiate an instance of the given type.	 *	 * @param  string  $type	 * @param  array   $parameters	 * @return mixed     * @throws \Exception	 */	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(), $parameters);		return $reflector->newInstanceArgs($dependencies);	}	/**	 * Resolve all of the dependencies from the ReflectionParameters.	 *	 * @param  array  $parameters	 * @param  array  $arguments that might have been passed into our resolve	 * @return array	 */	protected static function dependencies($parameters, $arguments)	{		$dependencies = array();		foreach ($parameters as $parameter)		{			$dependency = $parameter->getClass();			// If the person passed in some parameters to the class			// then we should probably use those instead of trying			// to resolve a new instance of the class			if (count($arguments) > 0)			{				$dependencies[] = array_shift($arguments);			}			else if (is_null($dependency))			{				$dependency[] = static::resolveNonClass($parameter);			}			else			{				$dependencies[] = static::resolve($dependency->name);			}		}		return (array) $dependencies;	}	/**	 * Resolves optional parameters for our dependency injection	 * pretty much took backport straight from L4's Illuminate\Container	 *	 * @param ReflectionParameter	 * @return default value     * @throws \Exception	 */	protected static function resolveNonClass($parameter)	{		if ($parameter->isDefaultValueAvailable())		{			return $parameter->getDefaultValue();		}		else		{			throw new \Exception("Unresolvable dependency resolving [$parameter].");		}	}}
 |