How to use Twig template engine with Yii2 framework? - php

I followed the instructions on yii2 documentation about using twig template engine
in config/web.php (which is included from index.php) I have:
'view' => [
'class' => 'yii\web\View',
'renderers' => [
'twig' => [
'class' => 'yii\twig\ViewRenderer',
'cachePath' => '#runtime/Twig/cache',
'options' => ['auto_reload' => true], /* Array of twig options */
'globals' => ['html' => '\yii\helpers\Html'],
],
],
],
in SiteController.php:
public function actionIndex()
{
echo $this->render('index.twig');
}
in views/site/index.twig I have some text:
But instead of seeing raw html I see template based on views/layouts/main.php with index.twig content used as variable in main layout.

It was required to set layout to false in order to skip layout processing during redner
class BaseController extends Controller
{
public $layout = false;
}

Related

Yii 2 and jQuery

Due project requirements I have to use a different version of jQuery than the one which comes with Yii2. I know I can disable it by using:
'assetManager' => [
'bundles' => [
// you can override AssetBundle configs here
'yii\web\JqueryAsset' => [
'sourcePath' => null,
'js' => []
],
],
],
Then I go to AppAsset:
class AppAsset extends AssetBundle
{
public $sourcePath = "#app/themes/v1/assets";
public $jsOptions = [ 'position' => \yii\web\View::POS_END ];
public $js = [
"js/lib/jquery/jquery-1.9.1.js",
];
}
But this brings one big issue, jquery loads after yii.validation, etc:
</script><script src="/assets/5b466ff1/yii.js?v=1465857632"></script>
<script src="/assets/5b466ff1/yii.validation.js?v=1465857632"></script>
<script src="/assets/5b466ff1/yii.activeForm.js?v=1465857632"></script>
<script src="/assets/98d185b3/js/lib/jquery/jquery-1.9.1.js?v=1466702133"></script>
My temporal solution is changing POS_END to POS_HEAD, but that affects page SEO right?, as far as I know is considered bad practice to load js on head.
So my question is:
How can I load jQuery from my theme assets, using POS_END and loading before yii.validation etc?
A possibility is to add it on web/js/jquery.js but I would prefer to keep it on the assets bundle.
Any ideas?
Update:
Adding this to AppAsset allows me to have control on the theme itself. It is cleaner than modifying the global config.
public function init()
{
parent::init();
Yii::$app->assetManager->bundles['yii\\web\\JqueryAsset'] = [
'js' => ['lib/jquery/jquery-1.9.1.js'],
'sourcePath' => '#app/themes/v1/assets/js'
];
}
Just Change Your Config Code as :
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => [
'js' => ['lib/jquery/jquery-1.9.1.js'],
'sourcePath' => '#app/themes/v1/assets/js'
]
]
]
No Need to Define jquery in AppAsset
class AppAsset extends AssetBundle
{
public $sourcePath = "#app/themes/v1/assets";
public $jsOptions = [ 'position' => \yii\web\View::POS_END ];
public $js = [
//"js/lib/jquery/jquery-1.9.1.js" Not Required
];
}

Yii2: configure yii\web\ViewAction::$viewPrefix

I want to change default directory ("pages") of static pages views, using yii\web\ViewAction. Documentation says:
You may configure yii\web\ViewAction::$viewPrefix to change the
directory for searching these views.
Question: where and how need I to change this property? I tried to do it in controller:
use yii\web\ViewAction;
...
public function actions()
{
(new ViewAction)->viewPrefix = ''; //wanted to do it just as '#app/views/site/', without any subdirectory ('pages' or others)
return [
'stat' => [
'class' => 'yii\web\ViewAction',
],
];
}
But no success.
Try to set viewPrefix to null
public function actions()
{
return [
'stat' => [
'class' => 'yii\web\ViewAction',
'viewPrefix' => null,
],
];
}

Yii2 routes definition in modules

Is there any solution to add routes from module configuration?
Example. We have main config where we describe
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => require(FILE_PATH_CONFIG_ENV . '_routes.php') // return array
],
]
in each module we load custom config file with private parameters
public function loadConfig($sFileName = 'main', $sFolderName = 'config')
{
Yii::configure($this, require($this->getBasePath() . DS . $sFolderName . DS . $sFileName . '.php'));
return $this;
}
Config file
return [
'components' => [
'urlManager' => [
'class' => 'yii\web\UrlManager',
'rules' => [
'/admin' => '/admin/index/index',
]
]
]
];
And now I need somehow merge current config (main for web application) with config loaded from module. In end I want describe in module config routes only for this module and use them for pretty urls (user friendly url). How can I do this one? This examples not working when I create url /admin/index/index, it shows me /admin/index/index but I want /admin as mentioned in module rules.
So I did this way (this is full answer for a question).
Create Bootstrap class special for module.
namespace app\extensions;
use yii\base\BootstrapInterface;
/**
* Class ModuleBootstrap
*
* #package app\extensions
*/
class ModuleBootstrap implements BootstrapInterface
{
/**
* #param \yii\base\Application $oApplication
*/
public function bootstrap($oApplication)
{
$aModuleList = $oApplication->getModules();
foreach ($aModuleList as $sKey => $aModule) {
if (is_array($aModule) && strpos($aModule['class'], 'app\modules') === 0) {
$sFilePathConfig = FILE_PATH_ROOT . DS . 'modules' . DS . $sKey . DS . 'config' . DS . '_routes.php';
if (file_exists($sFilePathConfig)) {
$oApplication->getUrlManager()->addRules(require($sFilePathConfig));
}
}
}
}
}
Create route file in module folder (/modules/XXX/config/_routes.php)
return [
'/sales' => '/sales/index/index',
'/sales/company' => '/sales/company/index',
'/sales/company/view/<sID:\d+>' => '/sales/company/view',
'/sales/company/update/<sID:\d+>' => '/sales/company/update',
'/sales/company/delete/<sID:\d+>' => '/sales/company/delete',
];
Add boostrap to main config file
$aConfig = [
// some code
'bootstrap' => [
// some code
'app\extensions\ModuleBootstrap',
],
'modules' => [
// some code
'sales' => ['class' => 'app\modules\sales\SalesModule']
]
]
return $aConfig;
That's it. We can define routes only in module 'route' config.
PS: I don't like detection if (is_array($aModule) && strpos($aModule['class'], 'app\modules') === 0) (I mean NOT 'debug', 'log', 'gii' or other native Yii2 modules) maybe someone can suggest better solution?
And this will be more clean and reliable. I have found this on Yii2's github repo here.
<?php
namespace backend\modules\webmasters;
use Yii;
use yii\base\BootstrapInterface;
class Module extends \yii\base\Module implements BootstrapInterface
{
public $controllerNamespace = 'backend\modules\webmasters\controllers';
public function init()
{
parent::init();
// initialize the module with the configuration loaded from config.php
Yii::configure($this, require(__DIR__ . '/config/main.php'));
}
/**
* #inheritdoc
*/
public function bootstrap($app)
{
$app->getUrlManager()->addRules([
[
'class' => 'yii\web\UrlRule',
'pattern' => $this->id,
'route' => $this->id . '/tools/index'
],
[
'class' => 'yii\web\UrlRule',
'pattern' => $this->id . '/<controller:[\w\-]+>/<action:[\w\-]+>',
'route' => $this->id . '/<controller>/<action>'
],
], false);
}
}
and just configure your main.php config file's bootstrap section as
'bootstrap' => [
'log',
'webmasters'
]
'modules' => [
'webmasters' => [
'class' => 'backend\modules\webmasters\Module'
]
]
Separating url rules for modules is mentioned in official documentation here.
And I think this is more optimum approach unlike merging and declaring all rules in one config file.
The rules are parsed in order they are declared (this is mentioned here), so with the separation you can skip other modules urls. In case of large amount of rules it can give perfomance boost.

Yii::configure does not work in module init()

I have a module calls API, and i want to load config file for it. The guide says that i have to use function \Yii::configure. I use it, but it doesn't apply any new configs. And i tried to use array instead config file, the result is same
class API extends \yii\base\Module
{
public $controllerNamespace = 'api\client\controllers';
public function init()
{
parent::init();
// \Yii::configure($this, require(__DIR__ . '/config/main.php'));
\yii::configure($this, [
'components' => [
'user' => [
'class' => 'yii\web\UserTest',
'identityClass' => 'api\client\models\User',
],
]
]);
echo \yii::$app->user->className();
die();
}
}
How I can override config in my module ?
UPDATE
You have to use setComponents method of Yii::$app
Yii::$app->setComponents(
[
'errorHandler'=>[
'errorAction'=>'forum/forum/error',
'class'=>'yii\web\ErrorHandler',
],
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'app\modules\profile\models\User',
],
]
);
OLD ANSWER
Didn't it give you errors? Your casing are wrong and so instead of "yii" in small letters use "Yii" capitalized
class API extends \yii\base\Module
{
public $controllerNamespace = 'api\client\controllers';
public function init()
{
parent::init();
\Yii::configure($this, [
'components' => [
'user' => [
'class' => 'yii\web\UserTest',
'identityClass' => 'api\client\models\User',
],
]
]);
echo \Yii::$app->user->className();
die();
}
}
I see no reason to override the application components here. I'd use #StefanoMtangoo trick but to set the component to the Module itself instead of Yii::$app:
public function init()
{
parent::init();
$this->setComponents([
'db' => [
'class' => 'yii2tech\filedb\Connection',
'path' => '#app/builder/data',
]
]);
}
Then the tricky part is to differentiate between any app's components and your module's own components. For example if my Module had a model extending yii\db\ActiveRecord I'd override its getDB() as follow (original code here):
public static function getDb()
{
return Yii::$app->getModule('api')->get('db');
// instead of: return Yii::$app->getDb();
}
So whatever the app that is using my module has or hasn't a db component it won't matter.

Yii2 override common extension/widget view

I have a widget class inside "~/common/extensions/my_widget"
It renders: "~/common/extensions/my_widget/views/index"
public function run()
{
echo $this->render( '#common/extensions/my_widget/views/index');
}
When i make a new application in "~/myapplication/"
how is it possible to override the widget view for only "myapplication" and if there is no view found, use the default view.
~ is my basefolder
Inside config, add your view:
'components' => [
...
'view'=> [
'theme' => [
'pathMap' => [
'#common/extensions/my_widget/views' => [
'#myapplication/views/widgets/my_widget/views', // Override
'#common/extensions/my_widget/views', // Default
],
],
],
]
],

Categories