first of all, your $config array must contain the following elements:
$config = [
//others
'modules' => [
'debug' => [
'class' => 'yii\debug\Module',
],
'gii' => [
'class' => 'yii\gii\Module',
];
],
//others
]
explain the inheritance relationship here:
class yii\base\Application extends yii\base\Module
class yii\base\Module extends yii\di\ServiceLocator
class yii\di\ServiceLocator extends yii\base\Component
class yii\base\Component extends yii\base\Object
< hr >
- yiibaseApplication::__construct () method comments
public function __construct($config = [])
{
Yii::$app = $this;
//\yii\base\ApplicationYii::$app->loadedModules
static::setInstance($this);
$this->state = self::STATE_BEGIN;
// :
$this->preInit($config);
//
$this->registerErrorHandler($config);
// __construct
// Component__construct
// `yii\base\Object__construct($config)`
Component::__construct($config);
}
in the above method Component::__construct ($config)
will call yii\ base\ Object::__construct ()
method
- yiibaseObject::__construct () method comments
public function __construct($config = [])
{
if (!empty($config)) {
// Object
// Object
// yii\web\Application
Yii::configure($this, $config);
}
$this->init();
}
< hr >
1. The following is just to explain where 'components' = > [' log' = > [.]]
comes from. If you don't care, you can go straight to the second step.
- first look at
$this- > preInit ($config);
, that is, yii\ base\ Application::preInit (& $config)
public function preInit(&$config)
{
//others...
// 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'])) {
// 'class'class
$config['components'][$id]['class'] = $component['class'];
}
}
}
/**
* Returns the configuration of core application components.
*
* @see set()
*/
public function coreComponents()
{
return [
//
'log' => ['class' => 'yii\log\Dispatcher'],
//others...
];
}
- after
$this- > preInit ($config);
, we get $config
$config = [
'modules' => [
'debug' => [
'class' => 'yii\debug\Module',
],
'gii' => [
'class' => 'yii\gii\Module',
];
],
'components' => [
'log' => [
'class' => 'yii\\log\\Dispatcher',
],
//others...
]
//others...
]
< hr >
< hr >
the above is just to explain 'components' = > [' log' = > [.]]
where it comes from
2. The key point is here
-
yii\ base\ Object::__construct ($config = [])
Yii::configure ($this, $config);
)
public static function configure($object, $properties)
{
//
foreach ($properties as $name => $value) {
$object->$name = $value;
}
return $object;
}
- here we need to cooperate with
yii\ base\ Object::__set ($name, $value)
/**
*
*
* Do not call this method directly as it is a PHP magic method that
* will be implicitly called when executing `$object->property = $value;`.
* PHP `$object->property = $value;`
*/
public function __set($name, $value)
{
// setter
// phpsetproperty() setProperty()
$setter = 'set' . $name;
if (method_exists($this, $setter)) {
// setter
$this->$setter($value);
} elseif (method_exists($this, 'get' . $name)) {
// gettersetter
throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
} else {
throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
}
}
$object
in the current context, we can think of it as yii\ base\ Application
$app
.
$app->modules = [
'debug' => [
'class' => 'yii\debug\Module',
],
'gii' => [
'class' => 'yii\gii\Module',
];
]
the yii\ base\ Module::setModules ($modules)
method will be called here
public function setModules($modules)
{
foreach ($modules as $id => $module) {
$this->_modules[$id] = $module;
}
}
so you have
in question.
["_modules":"yii\base\Module":private]=>
array(3) {
["debug"]=> object(yii\debug\Module)-sharp33 (28) {
......
}
["gii"]=> object(yii\gii\Module)-sharp113 (21) {
......
}
...
}
- the same thing, when traversing to:
$app->components = [
'log' => [
'class' => 'yii\\log\\Dispatcher',
],
]
- the
yii\ di\ ServiceLocator::setComponents ($components)
method
will be called here.
public function setComponents($components)
{
foreach ($components as $id => $component) {
$this->set($id, $component);
}
}
public function set($id, $definition)
{
// others ...
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)) {
// class
// a configuration array
if (isset($definition['class'])) {
// $_definitions
$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));
}
}
so you have
in question.
["_definitions":"yii\di\ServiceLocator":private]=>
array(24) {
["errorHandler"]=> .....
["request"]=> ......
["log"]=> ......
......
}