Commit 3d0a266a by Qiang Xue

Merge pull request #2788 from yiisoft/feature-container

DI container
parents f605508b b1c44162
......@@ -55,7 +55,7 @@ $object = Yii::createObject([
'class' => 'MyClass',
'property1' => 'abc',
'property2' => 'cde',
], $param1, $param2);
], [$param1, $param2]);
```
......
......@@ -93,26 +93,24 @@ In the above code, four components are configured: `cache`, `user`, `errorHandle
The configuration array has one special key named `class` that identifies the component's base class. The rest of the keys and values are used
to configure component properties in the same way as top-level keys are used to configure the application's properties.
Each application has a predefined set of components. To configure one of these, the `class` key can be omitted to use the default Yii class for that component. You can check the `registerCoreComponents()` method of the application you are using
Each application has a predefined set of components. To configure one of these, the `class` key can be omitted to use the default Yii class for that component. You can check the `coreComponents()` method of the application you are using
to get a list of component IDs and corresponding classes.
Note that Yii is smart enough to only configure the component when it's actually being used: for example, if you configure the `cache` component in your configuration file but never use the `cache` component in your code, no instance of that component will be created and no time is wasted configuring it.
Setting component defaults classwide
Setting component defaults class-wide
------------------------------------
For each component you can specifiy classwide defaults. For example, if you want to change the class used for all `LinkPager`
For each component you can specify class-wide defaults. For example, if you want to change the class used for all `LinkPager`
widgets without specifying the class for every widget usage, you can do the following:
```php
\Yii::$objectConfig = [
'yii\widgets\LinkPager' => [
'options' => [
'class' => 'pagination',
],
],
];
\Yii::$container->set('yii\widgets\LinkPager', [
'options' => [
'class' => 'pagination',
],
]);
```
The code above should be executed once before `LinkPager` widget is used. It can be done in `index.php`, the application
configuration file, or anywhere else.
\ No newline at end of file
configuration file, or anywhere else.
......@@ -71,7 +71,7 @@ $object = Yii::createObject([
'class' => 'MyClass',
'property1' => 'abc',
'property2' => 'cde',
], $param1, $param2);
], [$param1, $param2]);
```
More on configuration can be found in the [Basic concepts section](basics.md).
......
......@@ -164,7 +164,7 @@ class AuthAction extends Action
if (!empty($_GET[$this->clientIdGetParamName])) {
$clientId = $_GET[$this->clientIdGetParamName];
/** @var \yii\authclient\Collection $collection */
$collection = Yii::$app->getComponent($this->clientCollection);
$collection = Yii::$app->get($this->clientCollection);
if (!$collection->hasClient($clientId)) {
throw new NotFoundHttpException("Unknown auth client '{$clientId}'");
}
......
......@@ -143,7 +143,7 @@ class Choice extends Widget
protected function defaultClients()
{
/** @var $collection \yii\authclient\Collection */
$collection = Yii::$app->getComponent($this->clientCollection);
$collection = Yii::$app->get($this->clientCollection);
return $collection->getClients();
}
......
......@@ -86,7 +86,7 @@ class RequestPanel extends Panel
$action = null;
}
/** @var \yii\web\Session $session */
$session = Yii::$app->getComponent('session', false);
$session = Yii::$app->has('session', true) ? Yii::$app->get('session') : null;
return [
'flashes' => $session ? $session->getAllFlashes() : [],
......
......@@ -59,7 +59,7 @@ class ActiveRecord extends BaseActiveRecord
*/
public static function getDb()
{
return \Yii::$app->getComponent('elasticsearch');
return \Yii::$app->get('elasticsearch');
}
/**
......
......@@ -55,7 +55,7 @@ class DebugAction extends Action
$options = ['pretty' => true];
/** @var Connection $db */
$db = \Yii::$app->getComponent($this->db);
$db = \Yii::$app->get($this->db);
$time = microtime(true);
switch ($method) {
case 'GET': $result = $db->get($url, $options, $body, true); break;
......
......@@ -115,7 +115,7 @@ class Query extends Component implements QueryInterface
public function createCommand($db = null)
{
if ($db === null) {
$db = Yii::$app->getComponent('elasticsearch');
$db = Yii::$app->get('elasticsearch');
}
$commandConfig = $db->getQueryBuilder()->build($this);
......
......@@ -437,9 +437,9 @@ class Generator extends \yii\gii\Generator
*/
public function validateDb()
{
if (Yii::$app->hasComponent($this->db) === false) {
if (!Yii::$app->has($this->db)) {
$this->addError('db', 'There is no application component named "db".');
} elseif (!Yii::$app->getComponent($this->db) instanceof Connection) {
} elseif (!Yii::$app->get($this->db) instanceof Connection) {
$this->addError('db', 'The "db" application component must be a DB connection instance.');
}
}
......
......@@ -29,7 +29,7 @@ abstract class ActiveRecord extends BaseActiveRecord
*/
public static function getDb()
{
return \Yii::$app->getComponent('mongodb');
return \Yii::$app->get('mongodb');
}
/**
......
......@@ -9,6 +9,7 @@ namespace yii\mongodb;
use Yii;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* Cache implements a cache application component by storing cached data in a MongoDB.
......@@ -61,12 +62,7 @@ class Cache extends \yii\caching\Cache
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException($this->className() . "::db must be either a MongoDB connection instance or the application component ID of a MongoDB connection.");
}
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -62,7 +62,7 @@ class Query extends Component implements QueryInterface
public function getCollection($db = null)
{
if ($db === null) {
$db = Yii::$app->getComponent('mongodb');
$db = Yii::$app->get('mongodb');
}
return $db->getCollection($this->from);
......
......@@ -9,6 +9,7 @@ namespace yii\mongodb;
use Yii;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* Session extends [[\yii\web\Session]] by using MongoDB as session data storage.
......@@ -55,13 +56,8 @@ class Session extends \yii\web\Session
*/
public function init()
{
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException($this->className() . "::db must be either a MongoDB connection instance or the application component ID of a MongoDB connection.");
}
parent::init();
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -31,7 +31,7 @@ class Query extends \yii\mongodb\Query
public function getCollection($db = null)
{
if ($db === null) {
$db = Yii::$app->getComponent('mongodb');
$db = Yii::$app->get('mongodb');
}
return $db->getFileCollection($this->from);
......
......@@ -45,7 +45,7 @@ class ActiveRecord extends BaseActiveRecord
*/
public static function getDb()
{
return \Yii::$app->getComponent('redis');
return \Yii::$app->get('redis');
}
/**
......
......@@ -76,7 +76,7 @@ class Cache extends \yii\caching\Cache
{
parent::init();
if (is_string($this->redis)) {
$this->redis = Yii::$app->getComponent($this->redis);
$this->redis = Yii::$app->get($this->redis);
} elseif (is_array($this->redis)) {
if (!isset($this->redis['class'])) {
$this->redis['class'] = Connection::className();
......
......@@ -80,7 +80,7 @@ class Session extends \yii\web\Session
public function init()
{
if (is_string($this->redis)) {
$this->redis = Yii::$app->getComponent($this->redis);
$this->redis = Yii::$app->get($this->redis);
} elseif (is_array($this->redis)) {
if (!isset($this->redis['class'])) {
$this->redis['class'] = Connection::className();
......
......@@ -62,7 +62,7 @@ abstract class ActiveRecord extends BaseActiveRecord
*/
public static function getDb()
{
return \Yii::$app->getComponent('sphinx');
return \Yii::$app->get('sphinx');
}
/**
......
......@@ -155,7 +155,7 @@ class Query extends Component implements QueryInterface
*/
protected function defaultConnection()
{
return Yii::$app->getComponent('sphinx');
return Yii::$app->get('sphinx');
}
/**
......
......@@ -132,7 +132,7 @@ class Schema extends Object
if ($db->enableSchemaCache && !in_array($name, $db->schemaCacheExclude, true)) {
/** @var $cache Cache */
$cache = is_string($db->schemaCache) ? Yii::$app->getComponent($db->schemaCache) : $db->schemaCache;
$cache = is_string($db->schemaCache) ? Yii::$app->get($db->schemaCache, false) : $db->schemaCache;
if ($cache instanceof Cache) {
$key = $this->getCacheKey($name);
if ($refresh || ($index = $cache->get($key)) === false) {
......@@ -296,7 +296,7 @@ class Schema extends Object
public function refresh()
{
/** @var $cache Cache */
$cache = is_string($this->db->schemaCache) ? Yii::$app->getComponent($this->db->schemaCache) : $this->db->schemaCache;
$cache = is_string($this->db->schemaCache) ? Yii::$app->get($this->db->schemaCache, false) : $this->db->schemaCache;
if ($this->db->enableSchemaCache && $cache instanceof Cache) {
GroupDependency::invalidate($cache, $this->getCacheGroup());
}
......
......@@ -200,10 +200,9 @@ class Mailer extends BaseMailer
}
}
unset($config['constructArgs']);
array_unshift($args, $className);
$object = call_user_func_array(['Yii', 'createObject'], $args);
$object = Yii::createObject($className, $args);
} else {
$object = new $className;
$object = Yii::createObject($className);
}
if (!empty($config)) {
foreach ($config as $name => $value) {
......
......@@ -10,6 +10,7 @@ use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\base\UnknownClassException;
use yii\log\Logger;
use yii\di\Container;
/**
* Gets the application start timestamp.
......@@ -76,26 +77,13 @@ class BaseYii
*/
public static $aliases = ['@yii' => __DIR__];
/**
* @var array initial property values that will be applied to objects newly created via [[createObject]].
* The array keys are class names without leading backslashes "\", and the array values are the corresponding
* name-value pairs for initializing the created class instances. For example,
*
* ~~~
* [
* 'Bar' => [
* 'prop1' => 'value1',
* 'prop2' => 'value2',
* ],
* 'mycompany\foo\Car' => [
* 'prop1' => 'value1',
* 'prop2' => 'value2',
* ],
* ]
* ~~~
*
* @var Container the dependency injection (DI) container used by [[createObject()]].
* You may use [[Container::set()]] to set up the needed dependencies of classes and
* their initial property values.
* @see createObject()
* @see Container
*/
public static $objectConfig = [];
public static $container;
/**
......@@ -304,74 +292,59 @@ class BaseYii
/**
* Creates a new object using the given configuration.
*
* The configuration can be either a string or an array.
* If a string, it is treated as the *object class*; if an array,
* it must contain a `class` element specifying the *object class*, and
* the rest of the name-value pairs in the array will be used to initialize
* the corresponding object properties.
* You may view this method as an enhanced version of the `new` operator.
* The method supports creating an object based on a class name, a configuration array or
* an anonymous function.
*
* Below are some usage examples:
*
* ~~~
* $object = \Yii::createObject('app\components\GoogleMap');
* $object = \Yii::createObject([
* 'class' => 'app\components\GoogleMap',
* 'apiKey' => 'xyz',
* ```php
* // create an object using a class name
* $object = Yii::createObject('yii\db\Connection');
*
* // create an object using a configuration array
* $object = Yii::createObject([
* 'class' => 'yii\db\Connection',
* 'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
* 'username' => 'root',
* 'password' => '',
* 'charset' => 'utf8',
* ]);
* ~~~
*
* This method can be used to create any object as long as the object's constructor is
* defined like the following:
* // create an object with two constructor parameters
* $object = \Yii::createObject('MyClass', [$param1, $param2]);
* ```
*
* ~~~
* public function __construct(..., $config = []) {
* }
* ~~~
* Using [[\yii\di\Container|dependency injection container]], this method can also identify
* dependent objects, instantiate them and inject them into the newly created object.
*
* @param string|array|callable $type the object type. This can be specified in one of the following forms:
*
* The method will pass the given configuration as the last parameter of the constructor,
* and any additional parameters to this method will be passed as the rest of the constructor parameters.
* - a string: representing the class name of the object to be created
* - a configuration array: the array must contain a `class` element which is treated as the object class,
* and the rest of the name-value pairs will be used to initialize the corresponding object properties
* - a PHP callable: either an anonymous function or an array representing a class method (`[$class or $object, $method]`).
* The callable should return a new instance of the object being created.
*
* @param string|array $config the configuration. It can be either a string representing the class name
* or an array representing the object configuration.
* @return mixed the created object
* @param array $params the constructor parameters
* @return object the created object
* @throws InvalidConfigException if the configuration is invalid.
* @see \yii\di\Container
*/
public static function createObject($config)
public static function createObject($type, array $params = [])
{
static $reflections = [];
if (is_string($config)) {
$class = $config;
$config = [];
} elseif (isset($config['class'])) {
$class = $config['class'];
unset($config['class']);
} else {
if (is_string($type)) {
return static::$container->get($type, $params);
} elseif (is_array($type) && isset($type['class'])) {
$class = $type['class'];
unset($type['class']);
return static::$container->get($class, $params, $type);
} elseif (is_callable($type, true)) {
return call_user_func($type, $params);
} elseif (is_array($type)) {
throw new InvalidConfigException('Object configuration must be an array containing a "class" element.');
}
$class = ltrim($class, '\\');
if (isset(static::$objectConfig[$class])) {
$config = array_merge(static::$objectConfig[$class], $config);
}
if (func_num_args() > 1) {
/** @var \ReflectionClass $reflection */
if (isset($reflections[$class])) {
$reflection = $reflections[$class];
} else {
$reflection = $reflections[$class] = new \ReflectionClass($class);
}
$args = func_get_args();
array_shift($args); // remove $config
if (!empty($config)) {
$args[] = $config;
}
return $reflection->newInstanceArgs($args);
} else {
return empty($config) ? new $class : new $class($config);
throw new InvalidConfigException("Unsupported configuration type: " . gettype($type));
}
}
......
......@@ -248,7 +248,11 @@ Yii Framework 2 Change Log
- Chg: Added `View::viewFile` and removed `ViewEvent::viewFile` (qiangxue)
- Chg: Changed `Controller::afterAction()`, `Module::afterAction()` and `ActionFilter::afterAction()` to pass `$result` by value instead of reference (qiangxue)
- Chg: `yii\base\Extension::init()` is renamed to `bootstrap()` (qiangxue)
- Chg: `getComponent()` and `setComponent()` in `Application` and `Module` are renamed to `get()` and `set()` respectively. (qiangxue)
- Chg: The signature of `Yii::createObject()` is changed. Constructor parameters must be passed as the second parameter. (qiangxue)
- Chg: `Yii::$objectConfig` is removed. You should use `Yii::$container->set()` to configure default settings of classes. (qiangxue)
- New #66: [Auth client library](https://github.com/yiisoft/yii2-authclient) OpenId, OAuth1, OAuth2 clients (klimov-paul)
- New #503: Added `yii\di\Container` and `yii\di\ServiceLocator` (qiangxue)
- New #706: Added `yii\widgets\Pjax` and enhanced `GridView` to work with `Pjax` to support AJAX-update (qiangxue)
- New #1393: [Codeception testing framework integration](https://github.com/yiisoft/yii2-codeception) (Ragazzo)
- New #1438: [MongoDB integration](https://github.com/yiisoft/yii2-mongodb) ActiveRecord and Query (klimov-paul)
......
......@@ -24,3 +24,4 @@ class Yii extends \yii\BaseYii
spl_autoload_register(['Yii', 'autoload'], true, true);
Yii::$classMap = include(__DIR__ . '/classes.php');
Yii::$container = new yii\di\Container;
......@@ -160,7 +160,6 @@ abstract class Application extends Module
$this->preInit($config);
$this->registerErrorHandlers();
$this->registerCoreComponents();
Component::__construct($config);
}
......@@ -206,6 +205,15 @@ abstract class Application extends Module
} elseif (!ini_get('date.timezone')) {
$this->setTimeZone('UTC');
}
// merge core components with custom components
foreach ($this->coreComponents() as $id => $component) {
if (!isset($config['components'][$id])) {
$config['components'][$id] = $component;
} elseif (is_array($config['components'][$id]) && !isset($config['components'][$id]['class'])) {
$config['components'][$id]['class'] = $component['class'];
}
}
}
/**
......@@ -248,7 +256,7 @@ abstract class Application extends Module
*/
public function preloadComponents()
{
$this->getComponent('log');
$this->get('log');
parent::preloadComponents();
}
......@@ -400,7 +408,7 @@ abstract class Application extends Module
*/
public function getDb()
{
return $this->getComponent('db');
return $this->get('db');
}
/**
......@@ -409,7 +417,7 @@ abstract class Application extends Module
*/
public function getLog()
{
return $this->getComponent('log');
return $this->get('log');
}
/**
......@@ -418,7 +426,7 @@ abstract class Application extends Module
*/
public function getErrorHandler()
{
return $this->getComponent('errorHandler');
return $this->get('errorHandler');
}
/**
......@@ -427,7 +435,7 @@ abstract class Application extends Module
*/
public function getCache()
{
return $this->getComponent('cache');
return $this->get('cache');
}
/**
......@@ -436,7 +444,7 @@ abstract class Application extends Module
*/
public function getFormatter()
{
return $this->getComponent('formatter');
return $this->get('formatter');
}
/**
......@@ -445,7 +453,7 @@ abstract class Application extends Module
*/
public function getRequest()
{
return $this->getComponent('request');
return $this->get('request');
}
/**
......@@ -454,7 +462,7 @@ abstract class Application extends Module
*/
public function getView()
{
return $this->getComponent('view');
return $this->get('view');
}
/**
......@@ -463,7 +471,7 @@ abstract class Application extends Module
*/
public function getUrlManager()
{
return $this->getComponent('urlManager');
return $this->get('urlManager');
}
/**
......@@ -472,7 +480,7 @@ abstract class Application extends Module
*/
public function getI18n()
{
return $this->getComponent('i18n');
return $this->get('i18n');
}
/**
......@@ -481,7 +489,7 @@ abstract class Application extends Module
*/
public function getMail()
{
return $this->getComponent('mail');
return $this->get('mail');
}
/**
......@@ -490,16 +498,16 @@ abstract class Application extends Module
*/
public function getAuthManager()
{
return $this->getComponent('authManager');
return $this->get('authManager');
}
/**
* Registers the core application components.
* @see setComponents
* Returns the core application components.
* @see set
*/
public function registerCoreComponents()
public function coreComponents()
{
$this->setComponents([
return [
'log' => ['class' => 'yii\log\Logger'],
'errorHandler' => ['class' => 'yii\base\ErrorHandler'],
'formatter' => ['class' => 'yii\base\Formatter'],
......@@ -507,7 +515,7 @@ abstract class Application extends Module
'mail' => ['class' => 'yii\swiftmailer\Mailer'],
'urlManager' => ['class' => 'yii\web\UrlManager'],
'view' => ['class' => 'yii\web\View'],
]);
];
}
/**
......
......@@ -192,7 +192,7 @@ class Controller extends Component implements ViewContextInterface
$actionMap = $this->actions();
if (isset($actionMap[$id])) {
return Yii::createObject($actionMap[$id], $id, $this);
return Yii::createObject($actionMap[$id], [$id, $this]);
} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
$methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
if (method_exists($this, $methodName)) {
......
......@@ -8,6 +8,7 @@
namespace yii\base;
use Yii;
use yii\di\ServiceLocator;
/**
* Module is the base class for module and application classes.
......@@ -35,7 +36,7 @@ use Yii;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Module extends Component
class Module extends ServiceLocator
{
/**
* @var array custom module parameters (name => value).
......@@ -110,10 +111,7 @@ class Module extends Component
* @var array child modules of this module
*/
private $_modules = [];
/**
* @var array components registered under this module
*/
private $_components = [];
/**
* Constructor.
......@@ -129,38 +127,6 @@ class Module extends Component
}
/**
* Getter magic method.
* This method is overridden to support accessing components
* like reading module properties.
* @param string $name component or property name
* @return mixed the named property value
*/
public function __get($name)
{
if ($this->hasComponent($name)) {
return $this->getComponent($name);
} else {
return parent::__get($name);
}
}
/**
* Checks if a property value is null.
* This method overrides the parent implementation by checking
* if the named component is loaded.
* @param string $name the property name or the event name
* @return boolean whether the property value is null
*/
public function __isset($name)
{
if ($this->hasComponent($name)) {
return $this->getComponent($name) !== null;
} else {
return parent::__isset($name);
}
}
/**
* Initializes the module.
* This method is called after the module is created and initialized with property values
* given in configuration. The default implementation will call [[preloadComponents()]] to
......@@ -350,7 +316,7 @@ class Module extends Component
$this->_modules[$id]['class'] = 'yii\base\Module';
}
return $this->_modules[$id] = Yii::createObject($this->_modules[$id], $id, $this);
return $this->_modules[$id] = Yii::createObject($this->_modules[$id], [$id, $this]);
}
}
......@@ -432,126 +398,14 @@ class Module extends Component
}
/**
* Checks whether the named component exists.
* @param string $id component ID
* @return boolean whether the named component exists. Both loaded and unloaded components
* are considered.
*/
public function hasComponent($id)
{
return isset($this->_components[$id]);
}
/**
* Retrieves the named component.
* @param string $id component ID (case-sensitive)
* @param boolean $load whether to load the component if it is not yet loaded.
* @return Component|null the component instance, null if the component does not exist.
* @see hasComponent()
*/
public function getComponent($id, $load = true)
{
if (isset($this->_components[$id])) {
if ($this->_components[$id] instanceof Object) {
return $this->_components[$id];
} elseif ($load) {
return $this->_components[$id] = Yii::createObject($this->_components[$id]);
}
}
return null;
}
/**
* Registers a component with this module.
* @param string $id component ID
* @param Component|array|null $component the component to be registered with the module. This can
* be one of the followings:
*
* - a [[Component]] object
* - a configuration array: when [[getComponent()]] is called initially for this component, the array
* will be used to instantiate the component via [[Yii::createObject()]].
* - null: the named component will be removed from the module
*/
public function setComponent($id, $component)
{
if ($component === null) {
unset($this->_components[$id]);
} else {
$this->_components[$id] = $component;
}
}
/**
* Returns the registered components.
* @param boolean $loadedOnly whether to return the loaded components only. If this is set false,
* then all components specified in the configuration will be returned, whether they are loaded or not.
* Loaded components will be returned as objects, while unloaded components as configuration arrays.
* @return array the components (indexed by their IDs)
*/
public function getComponents($loadedOnly = false)
{
if ($loadedOnly) {
$components = [];
foreach ($this->_components as $component) {
if ($component instanceof Component) {
$components[] = $component;
}
}
return $components;
} else {
return $this->_components;
}
}
/**
* Registers a set of components in this module.
*
* Each component should be specified as a name-value pair, where
* name refers to the ID of the component and value the component or a configuration
* array that can be used to create the component. In the latter case, [[Yii::createObject()]]
* will be used to create the component.
*
* If a new component has the same ID as an existing one, the existing one will be overwritten silently.
*
* The following is an example for setting two components:
*
* ~~~
* [
* 'db' => [
* 'class' => 'yii\db\Connection',
* 'dsn' => 'sqlite:path/to/file.db',
* ],
* 'cache' => [
* 'class' => 'yii\caching\DbCache',
* 'db' => 'db',
* ],
* ]
* ~~~
*
* @param array $components components (id => component configuration or instance)
*/
public function setComponents($components)
{
foreach ($components as $id => $component) {
if (!is_object($component) && isset($this->_components[$id]['class']) && !isset($component['class'])) {
// set default component class
$component['class'] = $this->_components[$id]['class'];
}
$this->_components[$id] = $component;
}
}
/**
* Loads components that are declared in [[preload]].
* @throws InvalidConfigException if a component or module to be preloaded is unknown
*/
public function preloadComponents()
{
foreach ($this->preload as $id) {
if ($this->hasComponent($id)) {
$this->getComponent($id);
if ($this->has($id)) {
$this->get($id);
} elseif ($this->hasModule($id)) {
$this->getModule($id);
} else {
......@@ -635,7 +489,7 @@ class Module extends Component
return $module->createController($route);
}
if (isset($this->controllerMap[$id])) {
$controller = Yii::createObject($this->controllerMap[$id], $id, $this);
$controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
return [$controller, $route];
}
......
......@@ -11,6 +11,7 @@ use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\db\Query;
use yii\di\Instance;
/**
* DbCache implements a cache application component by storing cached data in a database.
......@@ -79,12 +80,7 @@ class DbCache extends Cache
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbCache::db must be either a DB connection instance or the application component ID of a DB connection.");
}
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -10,6 +10,7 @@ namespace yii\caching;
use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\di\Instance;
/**
* DbDependency represents a dependency based on the query result of a SQL statement.
......@@ -45,10 +46,7 @@ class DbDependency extends Dependency
*/
protected function generateDependencyData($cache)
{
$db = Yii::$app->getComponent($this->db);
if (!$db instanceof Connection) {
throw new InvalidConfigException("DbDependency::db must be the application component ID of a DB connection.");
}
$db = Instance::ensure($this->db, Connection::className());
if ($this->sql === null) {
throw new InvalidConfigException("DbDependency::sql must be set.");
}
......
......@@ -154,7 +154,7 @@ class Application extends \yii\base\Application
*/
public function getResponse()
{
return $this->getComponent('response');
return $this->get('response');
}
/**
......@@ -193,15 +193,13 @@ class Application extends \yii\base\Application
}
/**
* Registers the core application components.
* @see setComponents
* @inheritdoc
*/
public function registerCoreComponents()
public function coreComponents()
{
parent::registerCoreComponents();
$this->setComponents([
return array_merge([
'request' => ['class' => 'yii\console\Request'],
'response' => ['class' => 'yii\console\Response'],
]);
], parent::coreComponents());
}
}
......@@ -53,7 +53,7 @@ class CacheController extends Controller
public function actionFlush($component = 'cache')
{
/** @var Cache $cache */
$cache = Yii::$app->getComponent($component);
$cache = Yii::$app->get($component, false);
if (!$cache || !$cache instanceof Cache) {
throw new Exception('Application component "'.$component.'" is not defined or not a cache.');
}
......
......@@ -129,7 +129,7 @@ class MessageController extends Controller
}
}
} elseif ($config['format'] === 'db') {
$db = \Yii::$app->getComponent(isset($config['db']) ? $config['db'] : 'db');
$db = \Yii::$app->get(isset($config['db']) ? $config['db'] : 'db');
if (!$db instanceof \yii\db\Connection) {
throw new Exception('The "db" option must refer to a valid database application component.');
}
......
......@@ -122,7 +122,7 @@ class MigrateController extends Controller
if ($action->id !== 'create') {
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
$this->db = Yii::$app->get($this->db);
}
if (!$this->db instanceof Connection) {
throw new Exception("The 'db' option must refer to the application component ID of a DB connection.");
......
......@@ -13,6 +13,7 @@ use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\db\Connection;
use yii\db\QueryInterface;
use yii\di\Instance;
/**
* ActiveDataProvider implements a data provider based on [[\yii\db\Query]] and [[\yii\db\ActiveQuery]].
......@@ -85,10 +86,7 @@ class ActiveDataProvider extends BaseDataProvider
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
if ($this->db === null) {
throw new InvalidConfigException('The "db" property must be a valid DB Connection application component.');
}
$this->db = Instance::ensure($this->db, Connection::className());
}
}
......
......@@ -10,6 +10,7 @@ namespace yii\data;
use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\di\Instance;
/**
* SqlDataProvider implements a data provider based on a plain SQL statement.
......@@ -89,12 +90,7 @@ class SqlDataProvider extends BaseDataProvider
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException('The "db" property must be a valid DB Connection application component.');
}
$this->db = Instance::ensure($this->db, Connection::className());
if ($this->sql === null) {
throw new InvalidConfigException('The "sql" property must be set.');
}
......
......@@ -378,7 +378,7 @@ class Command extends \yii\base\Component
/** @var \yii\caching\Cache $cache */
if ($db->enableQueryCache && $method !== '') {
$cache = is_string($db->queryCache) ? Yii::$app->getComponent($db->queryCache) : $db->queryCache;
$cache = is_string($db->queryCache) ? Yii::$app->get($db->queryCache, false) : $db->queryCache;
}
if (isset($cache) && $cache instanceof Cache) {
......
......@@ -6,6 +6,7 @@
*/
namespace yii\db;
use yii\di\Instance;
/**
* Migration is the base class for representing a database migration.
......@@ -36,10 +37,10 @@ namespace yii\db;
class Migration extends \yii\base\Component
{
/**
* @var Connection the database connection that this migration should work with.
* If not set, it will be initialized as the 'db' application component.
* @var Connection|string the DB connection object or the application component ID of the DB connection
* that this migration should work with.
*/
public $db;
public $db = 'db';
/**
* Initializes the migration.
......@@ -48,9 +49,7 @@ class Migration extends \yii\base\Component
public function init()
{
parent::init();
if ($this->db === null) {
$this->db = \Yii::$app->getComponent('db');
}
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -96,7 +96,7 @@ abstract class Schema extends Object
if ($db->enableSchemaCache && !in_array($name, $db->schemaCacheExclude, true)) {
/** @var Cache $cache */
$cache = is_string($db->schemaCache) ? Yii::$app->getComponent($db->schemaCache) : $db->schemaCache;
$cache = is_string($db->schemaCache) ? Yii::$app->get($db->schemaCache, false) : $db->schemaCache;
if ($cache instanceof Cache) {
$key = $this->getCacheKey($name);
if ($refresh || ($table = $cache->get($key)) === false) {
......@@ -225,7 +225,7 @@ abstract class Schema extends Object
public function refresh()
{
/** @var Cache $cache */
$cache = is_string($this->db->schemaCache) ? Yii::$app->getComponent($this->db->schemaCache) : $this->db->schemaCache;
$cache = is_string($this->db->schemaCache) ? Yii::$app->get($this->db->schemaCache, false) : $this->db->schemaCache;
if ($this->db->enableSchemaCache && $cache instanceof Cache) {
GroupDependency::invalidate($cache, $this->getCacheGroup());
}
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\di;
use Yii;
use yii\base\InvalidConfigException;
/**
* Instance represents a reference to a named object in a dependency injection (DI) container or a service locator.
*
* You may use [[get()]] to obtain the actual object referenced by [[id]].
*
* Instance is mainly used in two places:
*
* - When configuring a dependency injection container, you use Instance to reference a class name, interface name
* or alias name. The reference can later be resolved into the actual object by the container.
* - In classes which use service locator to obtain dependent objects.
*
* The following example shows how to configure a DI container with Instance:
*
* ```php
* $container = new \yii\di\Container;
* $container->set('cache', 'yii\caching\DbCache', Instance::of('db'));
* $container->set('db', [
* 'class' => 'yii\db\Connection',
* 'dsn' => 'sqlite:path/to/file.db',
* ]);
* ```
*
* And the following example shows how a class retrieves a component from a service locator:
*
* ```php
* class DbCache extends Cache
* {
* public $db = 'db';
*
* public function init()
* {
* parent::init();
* $this->db = Instance::ensure($this->db, 'yii\db\Connection');
* }
* }
* ```
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Instance
{
/**
* @var string the component ID, class name, interface name or alias name
*/
public $id;
/**
* Constructor.
* @param string $id the component ID
*/
protected function __construct($id)
{
$this->id = $id;
}
/**
* Creates a new Instance object.
* @param string $id the component ID
* @return Instance the new Instance object.
*/
public static function of($id)
{
return new static($id);
}
/**
* Resolves the specified reference into the actual object and makes sure it is of the specified type.
*
* The reference may be specified as a string or an Instance object. If the former,
* it will be treated as a component ID, a class/interface name or an alias, depending on the container type.
*
* If you do not specify a container, the method will first try `Yii::$app` followed by `Yii::$container`.
*
* For example,
*
* ```php
* use yii\db\Connection;
*
* // returns Yii::$app->db
* $db = Instance::ensure('db', Connection::className());
* // or
* $instance = Instance::of('db');
* $db = Instance::ensure($instance, Connection::className());
* ```
*
* @param object|string|static $reference an object or a reference to the desired object.
* You may specify a reference in terms of a component ID or an Instance object.
* @param string $type the class/interface name to be checked. If null, type check will not be performed.
* @param ServiceLocator|Container $container the container. This will be passed to [[get()]].
* @return object the object referenced by the Instance, or `$reference` itself if it is an object.
* @throws InvalidConfigException if the reference is invalid
*/
public static function ensure($reference, $type = null, $container = null)
{
if ($reference instanceof $type) {
return $reference;
} elseif (empty($reference)) {
throw new InvalidConfigException('The required component is not specified.');
}
if (is_string($reference)) {
$reference = new static($reference);
}
if ($reference instanceof self) {
$component = $reference->get($container);
if ($component instanceof $type || $type === null) {
return $component;
} else {
throw new InvalidConfigException('"' . $reference->id . '" refers to a ' . get_class($component) . " component. $type is expected.");
}
}
$valueType = is_object($reference) ? get_class($reference) : gettype($reference);
throw new InvalidConfigException("Invalid data type: $valueType. $type is expected.");
}
/**
* Returns the actual object referenced by this Instance object.
* @param ServiceLocator|Container $container the container used to locate the referenced object.
* If null, the method will first try `Yii::$app` then `Yii::$container`.
* @return object the actual object referenced by this Instance object.
*/
public function get($container = null)
{
if ($container) {
return $container->get($this->id);
}
if (Yii::$app && Yii::$app->has($this->id)) {
return Yii::$app->get($this->id);
} else {
return Yii::$container->get($this->id);
}
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\di;
use Yii;
use Closure;
use yii\base\Component;
use yii\base\InvalidConfigException;
/**
* ServiceLocator implements a [service locator](http://en.wikipedia.org/wiki/Service_locator_pattern).
*
* To use ServiceLocator, you first need to register component IDs with the corresponding component
* definitions with the locator by calling [[set()]] or [[setComponents()]].
* You can then call [[get()]] to retrieve a component with the specified ID. The locator will automatically
* instantiate and configure the component according to the definition.
*
* For example,
*
* ```php
* $locator = new \yii\di\ServiceLocator;
* $locator->setComponents([
* 'db' => [
* 'class' => 'yii\db\Connection',
* 'dsn' => 'sqlite:path/to/file.db',
* ],
* 'cache' => [
* 'class' => 'yii\caching\DbCache',
* 'db' => 'db',
* ],
* ]);
*
* $db = $locator->get('db'); // or $locator->db
* $cache = $locator->get('cache'); // or $locator->cache
* ```
*
* Because [[\yii\base\Module]] extends from ServiceLocator, modules and the application are all service locators.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ServiceLocator extends Component
{
/**
* @var array shared component instances indexed by their IDs
*/
private $_components = [];
/**
* @var array component definitions indexed by their IDs
*/
private $_definitions = [];
/**
* Getter magic method.
* This method is overridden to support accessing components like reading properties.
* @param string $name component or property name
* @return mixed the named property value
*/
public function __get($name)
{
if ($this->has($name)) {
return $this->get($name);
} else {
return parent::__get($name);
}
}
/**
* Checks if a property value is null.
* This method overrides the parent implementation by checking if the named component is loaded.
* @param string $name the property name or the event name
* @return boolean whether the property value is null
*/
public function __isset($name)
{
if ($this->has($name, true)) {
return true;
} else {
return parent::__isset($name);
}
}
/**
* Returns a value indicating whether the locator has the specified component definition or has instantiated the component.
* This method may return different results depending on the value of `$checkInstance`.
*
* - If `$checkInstance` is false (default), the method will return a value indicating whether the locator has the specified
* component definition.
* - If `$checkInstance` is true, the method will return a value indicating whether the locator has
* instantiated the specified component.
*
* @param string $id component ID (e.g. `db`).
* @param boolean $checkInstance whether the method should check if the component is shared and instantiated.
* @return boolean whether the locator has the specified component definition or has instantiated the component.
* @see set()
*/
public function has($id, $checkInstance = false)
{
return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
}
/**
* Returns the component instance with the specified ID.
*
* @param string $id component ID (e.g. `db`).
* @param boolean $throwException whether to throw an exception if `$id` is not registered with the locator before.
* @return object|null the component of the specified ID. If `$throwException` is false and `$id`
* is not registered before, null will be returned.
* @throws InvalidConfigException if `$id` refers to a nonexistent component ID
* @see has()
* @see set()
*/
public function get($id, $throwException = true)
{
if (isset($this->_components[$id])) {
return $this->_components[$id];
}
if (isset($this->_definitions[$id])) {
$definition = $this->_definitions[$id];
if (is_object($definition) && !$definition instanceof Closure) {
return $this->_components[$id] = $definition;
} else {
return $this->_components[$id] = Yii::createObject($definition);
}
} elseif ($throwException) {
throw new InvalidConfigException("Unknown component ID: $id");
} else {
return null;
}
}
/**
* Registers a component definition with this locator.
*
* For example,
*
* ```php
* // a class name
* $locator->set('cache', 'yii\caching\FileCache');
*
* // a configuration array
* $locator->set('db', [
* 'class' => 'yii\db\Connection',
* 'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
* 'username' => 'root',
* 'password' => '',
* 'charset' => 'utf8',
* ]);
*
* // an anonymous function
* $locator->set('cache', function ($params) {
* return new \yii\caching\FileCache;
* });
*
* // an instance
* $locator->set('cache', new \yii\caching\FileCache);
* ```
*
* If a component definition with the same ID already exists, it will be overwritten.
*
* @param string $id component ID (e.g. `db`).
* @param mixed $definition the component definition to be registered with this locator.
* It can be one of the followings:
*
* - a class name
* - a configuration array: the array contains name-value pairs that will be used to
* initialize the property values of the newly created object when [[get()]] is called.
* The `class` element is required and stands for the the class of the object to be created.
* - a PHP callable: either an anonymous function or an array representing a class method (e.g. `['Foo', 'bar']`).
* The callable will be called by [[get()]] to return an object associated with the specified component ID.
* - an object: When [[get()]] is called, this object will be returned.
*
* @throws InvalidConfigException if the definition is an invalid configuration array
*/
public function set($id, $definition)
{
if ($definition === null) {
unset($this->_components[$id], $this->_definitions[$id]);
return;
}
if (is_object($definition) || is_callable($definition, true)) {
// an object, a class name, or a PHP callable
$this->_definitions[$id] = $definition;
} elseif (is_array($definition)) {
// a configuration array
if (isset($definition['class'])) {
$this->_definitions[$id] = $definition;
} else {
throw new InvalidConfigException("The configuration for the \"$id\" component must contain a \"class\" element.");
}
} else {
throw new InvalidConfigException("Unexpected configuration type for the \"$id\" component: " . gettype($definition));
}
}
/**
* Removes the component from the locator.
* @param string $id the component ID
*/
public function clear($id)
{
unset($this->_definitions[$id], $this->_components[$id]);
}
/**
* Returns the list of the component definitions or the loaded component instances.
* @param boolean $returnDefinitions whether to return component definitions instead of the loaded component instances.
* @return array the list of the component definitions or the loaded component instances (ID => definition or instance).
*/
public function getComponents($returnDefinitions = true)
{
return $returnDefinitions ? $this->_definitions : $this->_components;
}
/**
* Registers a set of component definitions in this locator.
*
* This is the bulk version of [[set()]]. The parameter should be an array
* whose keys are component IDs and values the corresponding component definitions.
*
* For more details on how to specify component IDs and definitions, please refer to [[set()]].
*
* If a component definition with the same ID already exists, it will be overwritten.
*
* The following is an example for registering two component definitions:
*
* ```php
* [
* 'db' => [
* 'class' => 'yii\db\Connection',
* 'dsn' => 'sqlite:path/to/file.db',
* ],
* 'cache' => [
* 'class' => 'yii\caching\DbCache',
* 'db' => 'db',
* ],
* ]
* ```
*
* @param array $components component definitions or instances
*/
public function setComponents($components)
{
foreach ($components as $id => $component) {
$this->set($id, $component);
}
}
}
......@@ -9,6 +9,7 @@ namespace yii\i18n;
use Yii;
use yii\base\InvalidConfigException;
use yii\di\Instance;
use yii\helpers\ArrayHelper;
use yii\caching\Cache;
use yii\db\Connection;
......@@ -93,19 +94,9 @@ class DbMessageSource extends MessageSource
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbMessageSource::db must be either a DB connection instance or the application component ID of a DB connection.");
}
$this->db = Instance::ensure($this->db, Connection::className());
if ($this->enableCaching) {
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
if (!$this->cache instanceof Cache) {
throw new InvalidConfigException("DbMessageSource::cache must be either a cache object or the application component ID of the cache object.");
}
$this->cache = Instance::ensure($this->cache, Cache::className());
}
}
......
......@@ -10,6 +10,7 @@ namespace yii\log;
use Yii;
use yii\db\Connection;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* DbTarget stores log messages in a database table.
......@@ -62,12 +63,7 @@ class DbTarget extends Target
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbTarget::db must be either a DB connection instance or the application component ID of a DB connection.");
}
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -9,6 +9,7 @@ namespace yii\log;
use Yii;
use yii\base\InvalidConfigException;
use yii\di\Instance;
use yii\mail\MailerInterface;
/**
......@@ -43,12 +44,7 @@ class EmailTarget extends Target
if (empty($this->message['to'])) {
throw new InvalidConfigException('The "to" option must be set for EmailTarget::message.');
}
if (is_string($this->mail)) {
$this->mail = Yii::$app->getComponent($this->mail);
}
if (!$this->mail instanceof MailerInterface) {
throw new InvalidConfigException("EmailTarget::mailer must be either a mailer object or the application component ID of a mailer object.");
}
$this->mail = Instance::ensure($this->mail, 'yii\mail\MailerInterface');
}
/**
......
......@@ -247,10 +247,10 @@ abstract class Target extends Component
$request = Yii::$app->getRequest();
$ip = $request instanceof Request ? $request->getUserIP() : '-';
/** @var \yii\web\User $user */
$user = Yii::$app->getComponent('user', false);
$user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
$userID = $user ? $user->getId(false) : '-';
/** @var \yii\web\Session $session */
$session = Yii::$app->getComponent('session', false);
$session = Yii::$app->has('session', true) ? Yii::$app->get('session') : null;
$sessionID = $session && $session->getIsActive() ? $session->getId() : '-';
return "[$ip] [$userID] [$sessionID]";
}
......
......@@ -10,6 +10,7 @@ namespace yii\mutex;
use Yii;
use yii\db\Connection;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* @author resurtm <resurtm@gmail.com>
......@@ -31,11 +32,6 @@ abstract class DbMutex extends Mutex
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException('Mutex::db must be either a DB connection instance or the application component ID of a DB connection.');
}
$this->db = Instance::ensure($this->db, Connection::className());
}
}
......@@ -15,6 +15,7 @@ use yii\base\Exception;
use yii\base\InvalidConfigException;
use yii\base\InvalidCallException;
use yii\base\InvalidParamException;
use yii\di\Instance;
/**
* DbManager represents an authorization manager that stores authorization information in database.
......@@ -59,14 +60,9 @@ class DbManager extends Manager
*/
public function init()
{
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbManager::db must be either a DB connection instance or the application component ID of a DB connection.");
}
$this->_usingSqlite = !strncmp($this->db->getDriverName(), 'sqlite', 6);
parent::init();
$this->db = Instance::ensure($this->db, Connection::className());
$this->_usingSqlite = !strncmp($this->db->getDriverName(), 'sqlite', 6);
}
/**
......
......@@ -10,6 +10,8 @@ namespace yii\test;
use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\di\Instance;
use yii\base\Object;
/**
* DbFixture is the base class for DB-related fixtures.
......@@ -34,11 +36,6 @@ abstract class DbFixture extends Fixture
public function init()
{
parent::init();
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!is_object($this->db)) {
throw new InvalidConfigException("The 'db' property must be either a DB connection instance or the application component ID of a DB connection.");
}
$this->db = Instance::ensure($this->db, Object::className());
}
}
......@@ -129,7 +129,7 @@ class Application extends \yii\base\Application
*/
public function getRequest()
{
return $this->getComponent('request');
return $this->get('request');
}
/**
......@@ -138,7 +138,7 @@ class Application extends \yii\base\Application
*/
public function getResponse()
{
return $this->getComponent('response');
return $this->get('response');
}
/**
......@@ -147,7 +147,7 @@ class Application extends \yii\base\Application
*/
public function getSession()
{
return $this->getComponent('session');
return $this->get('session');
}
/**
......@@ -156,7 +156,7 @@ class Application extends \yii\base\Application
*/
public function getUser()
{
return $this->getComponent('user');
return $this->get('user');
}
/**
......@@ -165,22 +165,20 @@ class Application extends \yii\base\Application
*/
public function getAssetManager()
{
return $this->getComponent('assetManager');
return $this->get('assetManager');
}
/**
* Registers the core application components.
* @see setComponents
* @inheritdoc
*/
public function registerCoreComponents()
public function coreComponents()
{
parent::registerCoreComponents();
$this->setComponents([
return array_merge([
'request' => ['class' => 'yii\web\Request'],
'response' => ['class' => 'yii\web\Response'],
'session' => ['class' => 'yii\web\Session'],
'user' => ['class' => 'yii\web\User'],
'assetManager' => ['class' => 'yii\web\AssetManager'],
]);
], parent::coreComponents());
}
}
......@@ -10,6 +10,7 @@ namespace yii\web;
use Yii;
use yii\caching\Cache;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* CacheSession implements a session component using cache as storage medium.
......@@ -52,13 +53,8 @@ class CacheSession extends Session
*/
public function init()
{
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
if (!$this->cache instanceof Cache) {
throw new InvalidConfigException('CacheSession::cache must refer to the application component ID of a cache object.');
}
parent::init();
$this->cache = Instance::ensure($this->cache, Cache::className());
}
/**
......
......@@ -11,6 +11,7 @@ use Yii;
use yii\db\Connection;
use yii\db\Query;
use yii\base\InvalidConfigException;
use yii\di\Instance;
/**
* DbSession extends [[Session]] by using database as session data storage.
......@@ -74,13 +75,8 @@ class DbSession extends Session
*/
public function init()
{
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("DbSession::db must be either a DB connection instance or the application component ID of a DB connection.");
}
parent::init();
$this->db = Instance::ensure($this->db, Connection::className());
}
/**
......
......@@ -145,7 +145,7 @@ class UrlManager extends Component
return;
}
if (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
$this->cache = Yii::$app->get($this->cache, false);
}
if ($this->cache instanceof Cache) {
$key = __CLASS__;
......
......@@ -11,6 +11,7 @@ use Yii;
use yii\base\Widget;
use yii\caching\Cache;
use yii\caching\Dependency;
use yii\di\Instance;
/**
*
......@@ -79,11 +80,7 @@ class FragmentCache extends Widget
{
parent::init();
if (!$this->enabled) {
$this->cache = null;
} elseif (is_string($this->cache)) {
$this->cache = Yii::$app->getComponent($this->cache);
}
$this->cache = $this->enabled ? Instance::ensure($this->cache, Cache::className()) : null;
if ($this->getCachedContent() === false) {
$this->getView()->cacheStack[] = $this;
......
......@@ -68,7 +68,7 @@ class MessageTest extends VendorTestCase
*/
protected function createTestMessage()
{
return Yii::$app->getComponent('mail')->compose();
return Yii::$app->get('mail')->compose();
}
/**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di;
use yii\di\Container;
use yii\di\Instance;
use yiiunit\framework\di\stubs\Bar;
use yiiunit\framework\di\stubs\Foo;
use yiiunit\framework\di\stubs\Qux;
use yiiunit\TestCase;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ContainerTest extends TestCase
{
public function testDefault()
{
$namespace = __NAMESPACE__ . '\stubs';
$QuxInterface = "$namespace\\QuxInterface";
$Foo = Foo::className();
$Bar = Bar::className();
$Qux = Qux::className();
// automatic wiring
$container = new Container;
$container->set($QuxInterface, $Qux);
$foo = $container->get($Foo);
$this->assertTrue($foo instanceof $Foo);
$this->assertTrue($foo->bar instanceof $Bar);
$this->assertTrue($foo->bar->qux instanceof $Qux);
// full wiring
$container = new Container;
$container->set($QuxInterface, $Qux);
$container->set($Bar);
$container->set($Qux);
$container->set($Foo);
$foo = $container->get($Foo);
$this->assertTrue($foo instanceof $Foo);
$this->assertTrue($foo->bar instanceof $Bar);
$this->assertTrue($foo->bar->qux instanceof $Qux);
// wiring by closure
$container = new Container;
$container->set('foo', function () {
$qux = new Qux;
$bar = new Bar($qux);
return new Foo($bar);
});
$foo = $container->get('foo');
$this->assertTrue($foo instanceof $Foo);
$this->assertTrue($foo->bar instanceof $Bar);
$this->assertTrue($foo->bar->qux instanceof $Qux);
// wiring by closure which uses container
$container = new Container;
$container->set($QuxInterface, $Qux);
$container->set('foo', function (Container $c, $params, $config) {
return $c->get(Foo::className());
});
$foo = $container->get('foo');
$this->assertTrue($foo instanceof $Foo);
$this->assertTrue($foo->bar instanceof $Bar);
$this->assertTrue($foo->bar->qux instanceof $Qux);
// predefined constructor parameters
$container = new Container;
$container->set('foo', $Foo, [Instance::of('bar')]);
$container->set('bar', $Bar, [Instance::of('qux')]);
$container->set('qux', $Qux);
$foo = $container->get('foo');
$this->assertTrue($foo instanceof $Foo);
$this->assertTrue($foo->bar instanceof $Bar);
$this->assertTrue($foo->bar->qux instanceof $Qux);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di;
use yii\base\Component;
use yii\di\Container;
use yii\di\Instance;
use yiiunit\TestCase;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class InstanceTest extends TestCase
{
public function testOf()
{
$container = new Container;
$className = Component::className();
$instance = Instance::of($className, $container);
$this->assertTrue($instance instanceof Instance);
$this->assertTrue($instance->get() instanceof Component);
$this->assertTrue(Instance::ensure($instance, $className) instanceof Component);
$this->assertTrue($instance->get() !== Instance::ensure($instance, $className));
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di;
use yii\base\Object;
use yii\di\ServiceLocator;
use yiiunit\TestCase;
class Creator
{
public static function create()
{
return new TestClass;
}
}
class TestClass extends Object
{
public $prop1 = 1;
public $prop2;
}
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ServiceLocatorTest extends TestCase
{
public function testCallable()
{
// anonymous function
$container = new ServiceLocator;
$className = TestClass::className();
$container->set($className, function () {
return new TestClass([
'prop1' => 100,
'prop2' => 200,
]);
});
$object = $container->get($className);
$this->assertTrue($object instanceof $className);
$this->assertEquals(100, $object->prop1);
$this->assertEquals(200, $object->prop2);
// static method
$container = new ServiceLocator;
$className = TestClass::className();
$container->set($className, [__NAMESPACE__ . "\\Creator", 'create']);
$object = $container->get($className);
$this->assertTrue($object instanceof $className);
$this->assertEquals(1, $object->prop1);
$this->assertNull($object->prop2);
}
public function testObject()
{
$object = new TestClass;
$className = TestClass::className();
$container = new ServiceLocator;
$container->set($className, $object);
$this->assertTrue($container->get($className) === $object);
}
public function testShared()
{
// with configuration: shared
$container = new ServiceLocator;
$className = TestClass::className();
$container->set($className, [
'class' => $className,
'prop1' => 10,
'prop2' => 20,
]);
$object = $container->get($className);
$this->assertEquals(10, $object->prop1);
$this->assertEquals(20, $object->prop2);
$this->assertTrue($object instanceof $className);
// check shared
$object2 = $container->get($className);
$this->assertTrue($object2 instanceof $className);
$this->assertTrue($object === $object2);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di\stubs;
use yii\base\Object;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Bar extends Object
{
public $qux;
public function __construct(QuxInterface $qux, $config = [])
{
$this->qux = $qux;
parent::__construct($config);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di\stubs;
use yii\base\Object;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Foo extends Object
{
public $bar;
public function __construct(Bar $bar, $config = [])
{
$this->bar = $bar;
parent::__construct($config);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di\stubs;
use yii\base\Object;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Qux extends Object implements QuxInterface
{
public $a;
public function __construct($a = 1, $config = [])
{
$this->a = $a;
parent::__construct($config);
}
public function quxMethod()
{
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di\stubs;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
interface QuxInterface
{
function quxMethod();
}
......@@ -59,7 +59,7 @@ class BaseMailerTest extends TestCase
*/
protected function getTestMailComponent()
{
return Yii::$app->getComponent('mail');
return Yii::$app->get('mail');
}
// Tests :
......
......@@ -36,7 +36,7 @@ class BaseMessageTest extends TestCase
*/
protected function getMailer()
{
return Yii::$app->getComponent('mail');
return Yii::$app->get('mail');
}
// Tests :
......
......@@ -58,7 +58,7 @@ class ActiveFixtureTest extends DatabaseTestCase
public function setUp()
{
parent::setUp();
\Yii::$app->setComponent('db', $this->getConnection());
\Yii::$app->set('db', $this->getConnection());
ActiveRecord::$db = $this->getConnection();
}
......
......@@ -15,7 +15,7 @@ class CacheSessionTest extends \yiiunit\TestCase
{
parent::setUp();
$this->mockApplication();
Yii::$app->setComponent('cache', new FileCache());
Yii::$app->set('cache', new FileCache());
}
public function testCacheSession()
......@@ -30,7 +30,7 @@ class CacheSessionTest extends \yiiunit\TestCase
public function testInvalidCache()
{
$this->setExpectedException('yii\base\InvalidConfigException');
$this->setExpectedException('\Exception');
new CacheSession(['cache' => 'invalid']);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment