If I use view component like the document says
return [
'components' => [
'view' => [
'theme' => [
'basePath' => '@app/themes/basic',
'baseUrl' => '@web/themes/basic',
'pathMap' => [
'@app/views' => '@app/themes/basic',
],
],
],
],
];
does it means that the main.php in the folder @app/themes/basic/layouts/main.php will replace the main.php in the folder @app/views/layouts/main.php ?
and how yii2 achieve this? I couldn't figure out though I traced the controller to find something which could help me understand the logic.
I traced the codes as following, but I didn't find out how the layout main.php been replaced when using themes.
1.SiteController, default action index, then render the view
public function actionIndex()
{
return $this->render('index');
}
2.call the Controller class function render
public function render($view, $params = [])
{
$content = $this->getView()->render($view, $params, $this);
return $this->renderContent($content);
}
3.get the yii\web\View
public function getView()
{
if ($this->_view === null) {
$this->_view = Yii::$app->getView();
}
return $this->_view;
}
4.use the View class function render
public function render($view, $params = [], $context = null)
{
$viewFile = $this->findViewFile($view, $context);
return $this->renderFile($viewFile, $params, $context);
}
5.find view file, get the view file path
protected function findViewFile($view, $context = null)
{
if (strncmp($view, '@', 1) === 0) {
// e.g. "@app/views/main"
$file = Yii::getAlias($view);
} elseif (strncmp($view, '//', 2) === 0) {
// e.g. "//layouts/main"
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} elseif (strncmp($view, '/', 1) === 0) {
// e.g. "/site/index"
if (Yii::$app->controller !== null) {
$file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} else {
throw new InvalidCallException("Unable to locate view file for view '$view': no active controller.");
}
} elseif ($context instanceof ViewContextInterface) {
$file = $context->getViewPath() . DIRECTORY_SEPARATOR . $view;
} elseif (($currentViewFile = $this->getViewFile()) !== false) {
$file = dirname($currentViewFile) . DIRECTORY_SEPARATOR . $view;
} else {
throw new InvalidCallException("Unable to resolve view file for view '$view': no active view context.");
}
if (pathinfo($file, PATHINFO_EXTENSION) !== '') {
return $file;
}
$path = $file . '.' . $this->defaultExtension;
if ($this->defaultExtension !== 'php' && !is_file($path)) {
$path = $file . '.php';
}
return $path;
}
6.render this view file
public function renderFile($viewFile, $params = [], $context = null)
{
$viewFile = Yii::getAlias($viewFile);
if ($this->theme !== null) {
$viewFile = $this->theme->applyTo($viewFile);
}
if (is_file($viewFile)) {
$viewFile = FileHelper::localize($viewFile);
} else {
throw new ViewNotFoundException("The view file does not exist: $viewFile");
}
$oldContext = $this->context;
if ($context !== null) {
$this->context = $context;
}
$output = '';
$this->_viewFiles[] = $viewFile;
if ($this->beforeRender($viewFile, $params)) {
Yii::trace("Rendering view file: $viewFile", __METHOD__);
$ext = pathinfo($viewFile, PATHINFO_EXTENSION);
if (isset($this->renderers[$ext])) {
if (is_array($this->renderers[$ext]) || is_string($this->renderers[$ext])) {
$this->renderers[$ext] = Yii::createObject($this->renderers[$ext]);
}
/* @var $renderer ViewRenderer */
$renderer = $this->renderers[$ext];
$output = $renderer->render($this, $viewFile, $params);
} else {
$output = $this->renderPhpFile($viewFile, $params);
}
$this->afterRender($viewFile, $params, $output);
}
array_pop($this->_viewFiles);
$this->context = $oldContext;
return $output;
}
7.if the theme is not null, the system will call the $this->theme->applyTo($viewFile) to get the theme view file, and renderPhpFile
$output = $this->renderPhpFile($viewFile, $params);
8.get the content of this file
This happen because when Yii2 perform a render check in config / components the real mapping for views container direrctory.
This can be related to all the views as in your case
or can be related to some vendor or modulo as
you can take a look at reference doc for views http://www.yiiframework.com/doc-2.0/yii-base-view.html
and https://github.com/yiisoft/yii2/blob/master/framework/base/View.php