Overview

Namespaces

  • Syringe
    • Exceptions

Classes

  • Syringe\Container
  • Syringe\Resolver

Exceptions

  • Syringe\Exceptions\ContainerValueNotFoundException
  • Syringe\Exceptions\UnableToResolveException
  • Overview
  • Namespace
  • Class
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26: 
             27:  28:  29:  30:  31:  32: 
             33:  34: 
             35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46: 
             47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66: 
             67:  68: 
             69:  70:  71:  72:  73:  74:  75:  76:  77:  78: 
             79:  80:  81:  82:  83:  84:  85:  86:  87:  88: 
             89:  90: 
             91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 
<?php

namespace Syringe;

use Interop\Container\ContainerInterface;
use Syringe\Exceptions\ContainerValueNotFoundException;

/**
 * The Container. Used to hold, modify, and retrieve bindings of parameters and services.
 *
 * Class Container
 * @package Syringe
 */
class Container implements ContainerInterface
{
    /**
     * @var array
     */
    protected static $instanceBindings;

    /**
     * @var array
     */
    protected static $valueBindings;

    /**
     * @var array
     */
    protected static $classBindings;

    /**
     * Shared services which have been instantiated by the container
     *
     * @var array
     */
    protected static $instances;

    /**
     * @var array
     */
    protected static $extensions;

    /**
     * Bind a class or parameter to the container
     *
     * @param string $key
     * @param callable|object|mixed $value
     */
    public function bind(string $key, $value)
    {
        if (is_object($value)) {
            $this->bindInstance($key, $value);
        } else if (interface_exists($key) || class_exists($key)) {
            $this->bindClass($key, $value);
        } else if (is_callable($value)) {
            $this->bindClass($key, $value);
        } else if (is_string($value) && class_exists($value)) {
            $this->bindClass($key, $value);
        } else {
            $this->bindValue($key, $value);
        }
    }

    /**
     * Bind a class to the container
     *
     * @param string $key
     * @param $value
     */
    public function bindClass(string $key, $value)
    {
        self::$classBindings[$key] = $value;
    }

    /**
     * Bind an object instance to the container
     *
     * @param string $key
     * @param $object
     */
    public function bindInstance(string $key, $object)
    {
        self::$instanceBindings[$key] = $object;
        unset(self::$instances[$key]);
    }

    /**
     * Bind a primitive value to the cntainer
     *
     * @param string $key
     * @param mixed $value
     */
    public function bindValue(string $key, $value)
    {
        self::$valueBindings[$key] = $value;
    }

    /**
     * @inheritdoc
     */
    public function get($key)
    {
        if (isset(self::$valueBindings[$key])) {
            $result = self::$valueBindings[$key];
            if (is_callable($result)) {
                $result = call_user_func_array($result(), [$this]);
            }
        } else if (isset(self::$instanceBindings[$key])) {
            //check if already instantiated
            if (isset(self::$instances[$key])) {
                $result = self::$instances[$key];
            } else if (is_callable($result = self::$instanceBindings[$key])) {
                $result = call_user_func_array($result, [$this]);
                self::$instances[$key] = $result;
            } else if (is_string($result) && class_exists($result)) {
                // if object name
                $result = new $result();
            }
            //if object
        } else if (isset(self::$classBindings[$key])) {
            if (is_callable($result = self::$classBindings[$key])) {
                $result = call_user_func_array($result, [$this]);
            } else if (is_string($result) && class_exists($result)) {
                $result = new $result();
            }
            // if primitive
        } else {
            throw new ContainerValueNotFoundException("You haven't bound anything for $key");
        }

        //execute any extensions
        if(isset(self::$extensions[$key])) {
            foreach (self::$extensions[$key] as $extra) {
                $result = call_user_func_array($extra, [$result, $this]);
            }
        }
        return $result;
    }

    /**
     * @inheritdoc
     */
    public function has($key)
    {
        return isset(self::$valueBindings[$key]) || isset(self::$instanceBindings[$key]) || isset(self::$classBindings[$key]);
    }

    /**
     * Modify an already bound value
     *
     * @param string $key
     * @param callable $func
     */
    public function extend(string $key, callable $func)
    {
        if(!$this->has($key)) {
            throw new ContainerValueNotFoundException("You haven't bound anything for $key");
        }
        if(isset(self::$extensions[$key])) {
            self::$extensions[$key][] = $func;
        } else {
            self::$extensions[$key] = [$func];
        }
    }

    /**
     * Retrieve the original raw binding for a bound value (without evaluating)
     *
     * @param string $key
     * @return mixed
     */
    public function raw(string $key)
    {
        if (isset(self::$valueBindings[$key])) {
            $result = self::$valueBindings[$key];
        } else if (isset(self::$instanceBindings[$key])) {
            $result = self::$instanceBindings[$key];
        } else if (isset(self::$classBindings[$key])) {
            $result = self::$classBindings[$key];
        } else {
            throw new ContainerValueNotFoundException("You haven't bound anything for $key.");
        }

        return $result;
    }
}
API documentation generated by ApiGen