Theme based module's views in yii2 - yii2

I am using Yii2 Advanced Template. I have created user module inside /frontend/modules/ directory. without theme integration, views are called from /modules/user/views/ directory.
Currently, I have created three different themes inside /frontend directory. So I would like to access views from theme directory for User Module. How it would be possible?
It is possible to set layout for module by
$this->layoutPath = \Yii::getAlias('/themes/classic/views/layouts/');
$this->layout = 'userLayout';
But How views can be accessed from theme directory for module?
Please suggest possible solutions..

I found solution to my question. I have implemented following way.
Added Layout path in Module.php after init() method.
public function init()
{
parent::init();
$this->layoutPath = \Yii::getAlias('#app/themes/classic/views/layouts/');
$this->layout = 'userLayout';
}
and
added theme configuration with module views in main.php config file
'view' => [
'theme' => [
'pathMap' => [
'#app/views' =>'#app/themes/classic/views/',
'#app/modules'=>'#app/themes/classic/modules',
'#app/widgets'=>'#app/themes/classic/widgets'
],
'baseUrl'=>"/themes/classic",
],
],

Related

Yii 2 Module wise configuration setting

I have setup Yii2 nested module and I want to set different configuration and each modules has own component and other settings with there own models
Like in School Management System, I have created a nested module like V1 is my API (main module) and under these, I have created a Student module, Teacher module, Parent module, driver module, admin module each has a different table and different model. I want to login differently with each user like..
API calls for each
https://example.com/v1/admin/login
https://example.com/v1/student/login
https://example.com/v1/parent/login
https://example.com/v1/user/login
https://example.com/v1/driver/login
How can I manage these login and their own configuration?
Thanks
Jitendra
In the module Class you can set components, aliases and other settings and using something like this:
Here is an example for the admin module:
class Admin extends Module
{
// ...
/**
* {#inheritdoc}
*/
public function init()
{
parent::init();
// custom initialization code goes here
$this->setComponents([
// array of components
]);
// ...
}
}
or if you prefer you can set the components like this
$this->components = [
// array of components
]);
if you are using nested modules, you are already specifying "settings" for the module - i.e all sub modules
To use different login for all modules when specifying components set different name for the identityCookie of the user component for each module.
Example for admin module:
$this->components => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-admin', 'httpOnly' => true],
],
// ... other components

Yii2 How to correctly register a CSS file

I'm trying to register a CSS file in this way
$this->registerCssFile('../node_modules/fullcalendar/dist/fullcalendar.css', [
'depends' => [\yii\web\JqueryAsset::className()]
]);
But I get the error:
Failed to load a resource.
For instance, I know that I am standing at web folder, so that's why I wrote the above code in that way.
I tried without the registerCssFile and I achieved it writing directly this in the view file:
<link href="../node_modules/fullcalendar/dist/fullcalendar.css" rel="stylesheet">
Therefore I think the error is in the registerCssFile cause when I inspect in the browser this method add a slash (/) before all the relative path:
<link href="/../node_modules/fullcalendar/dist/fullcalendar.css" rel="stylesheet">
Anyway, THE QUESTION is how can I do to achieve it with regiserCssFile(the correct way)?
Or how can I remove that slash?
Just in case:
/yii2app
|_/views
|_/whatever
|_myview.php
|_/web
|_/node_modules
|_/fullcalendar
|_/dist
|_fullcalendar.css
The first thing that I would advise you is to move the folder inside the web directory and remove the trailing ../ from the URL.
Like below
$this->registerCssFile('node_modules/fullcalendar/dist/fullcalendar.css', [
'depends' => [\yii\web\JqueryAsset::className()]
]);
The /yii2app/web directory is where your application Entry script is running from so you do not need to provide a path relative to the view file, but the web directory.
Otherwise, use AssetManager to load assets from outside the web directory and use the $sourcePath option to use the directory outside the web.
see below a demo for Asset manager.
namespace app\assets;
use Yii;
use yii\web\AssetBundle;
use yii\web\View;
// set #themes alias so we do not have to update baseUrl every time we change themes
Yii::setAlias('#themes', Yii::$app->view->theme->baseUrl);
/**
* Main frontend application asset bundle.
*/
class FullCalendarAsset extends AssetBundle
{
public $sourcePath = '#app/node_modules/';
public $css = [
'fullcalendar/dist/_fullcalendar.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
'yii\bootstrap\BootstrapPluginAsset',
];
}
place the above file inside the app/assets directory and then inside your view
use app\assets\FullCalendarAsset;
FullCalendarAsset::register($this);
you should learn about the application LIFE CYCLE.

Yii2 custom gii generator and template?

I just implementing a new gii generator for my requirement on yii2.
i want to know best place to keep those codes?
Create app\modules\gii directory with own Generator class, views, templates.
namespace app\modules\gii;
class MyCustomGenerator extends \yii\gii\generators\crud\Generator
{
// ...
public function generate()
{
// ...
}
}
Then enable it in gii configuration.
[
// ...
'modules' => [
'gii' => [
'class' => 'yii\gii\Module',
'generators' => [
'class' => '\app\modules\gii\MyCustomGenerator',
'model' => ['class' => '\app\modules\gii\model\MyCustomGenerator'],
],
],
],
]
Which module of gii that you need to custom?
If it is CRUD module, I think you should put it into app/backend/ because it just use for this app.
Here is my customization: custom crud gii templates
My folder structure: yii2 - custom gii crud templates - folder structure
No good idea own gii template put in app/modules/gii. Better is create separate module. Benefits:
can reuse in other projects
if put it in composer under require_dev, do not install on production

Yii2 - module login in basic application template

Using the "basic" application template, what is the correct way of setting up a module login that is separate from the main site login?
For example I have an "admin" module which requires a login. I also need a user login for the main site.
I have done the following:
Created admin module using gii tool
Created models folder within the admin module folder
Placed LoginForm.php and User.php within this folder (also updated the namespace declarations in these files)
Added AccessControl behaviour and login/logout actions to modules\admin\controllers\DefaultController.php
Updated config\web.php as follows:
'modules' => [
'admin' => [
'class' => 'app\modules\admin\Module',
],
],
Updated app\modules\admin\Module.php as follows:
public function init()
{
parent::init();
Yii::$app->set('user', [
'class' => 'yii\web\User',
'identityClass' => 'app\modules\admin\models\User',
'enableAutoLogin' => true,
'loginUrl' => ['admin/default/login'],
]);
Yii::$app->set('session', [
'class' => 'yii\web\Session',
'name' => '_adminSessionId',
]);
}
The problem I am having is that if I try to access an admin page when I am not logged in, it shows the login form (this is correct). However upon logging in, it is just redirects me back to the main site. It should redirect me to the admin page I was trying to access.
In DefaultController.php, it has the following (default code):
if ($model->load(Yii::$app->request->post()) && $model->login())
return $this->goBack();
What is the correct way of doing this so I can have independent logins for the admin module and for the main site? I don't want to use the "advanced application template" as that adds some unnecessary complexity.
The User component allows you to set a returnUrl, the getter explained: This method reads the return URL from the session. It is usually used by the login action which may call this method to redirect the browser to where it goes after successful authentication.
Recommended: Before processing the data, set the returnUrl by calling Yii::$app->user->setReturnUrl(Url::current()); (this will store the page the user was on in the session, moreover, you can manipulate GET parameters using Url::current() before passing it to the session), and let the framework do its magic.
Not recommended: After processing the data, you can rely on referrer (which won't work in some cases) as following
return Yii::$app->request->referrer ? $this->redirect(Yii::$app->request->referrer) : $this->goHome(); or instead of goHome which basically redirects to app->homeUrl that can be set during Module init, you could say $this->redirect('your/admin/index');
I recommend setting the ['homeUrl' => 'your/admin/index'] during the initialization of the Module, as you might need it for other features as well and Yii2 uses it as a "fallback" to some redirects as well.
The best way is to create new controller in the admin module, which should have login, logout actions. Because, in future you may add there some extra logic.
In that login action you can use same LoginForm.
You can specify redirect url in that login action.
Admin module class can looks like this:
namespace app\modules\admin;
class Module extends \yii\base\Module
{
public $layout = 'main';
public $defaultRoute = 'main/index';
public function init()
{
parent::init();
Yii::$app->errorHandler->errorAction = '/admin/main/error';
Yii::$app->user->loginUrl = '/admin/main/login';
.....
}
}
goBack() defaults to the homeUrl if the returnUrl for the user hasn't been set.
Why not just redirect?
if ($model->load(Yii::$app->request->post()) && $model->login())
return $this->redirect(['myadminmodule']);
go to config/web.php and add it to the components
'backendUrlManager'=>[
'class' => 'yii\web\urlManager',
'enablePrettyUrl'=>true,
'showScriptName'=>false,
'baseUrl'=>'/admin',
],
In DefaultController.php, it has the following (default code):
if ($model->load(Yii::$app->request->post()) && $model->login())
return Yii::$app->getResponse()->redirect(Yii::$app->backendUrlManager->baseUrl);

Yii2 How to enable default assets only in certain modules

I am using basic yii2 app, I have disabled the boostrap css and js in web.php config but i want to enable it inside the module called admin.
I tried adding like this, for component section in config.php under admin module folder, but no luck!
'assetManager' => [
'bundles' => [
'yii\bootstrap\BootstrapPluginAsset' => [
'js'=> ['js/boostrap.js']
],
'yii\bootstrap\BootstrapAsset' => [
'css' => ['css/boostrap.min.css']
]
],
],
How can i achieve this?
In your module's init() method, you can override an exist asset bundle like below:
public function init() {
\Yii::$app->assetManager->bundles['yii\bootstrap\BootstrapAsset'] = [
'css' => ['css/bootstrap_NEW.css']
];
parent::init();
}
In above example, we override yii\bootstrap\BootstrapAsset CSS file in our module. So, in this module, it uses bootstrap_NEW.css instead of its default.
Please note that, you can do this in application globally, not specially in module's init() method. It was just a suggestion to solve this specific case.
You should use asset bundles to handle this, no need to modify assetManager.
To disable Bootstrap, simply remove it from $depends in AppAsset :
public $depends = [
'yii\web\YiiAsset',
];
Create a ModuleAsset class in your module :
class ModuleAsset extends \yii\web\AssetBundle
{
public $depends = [
'yii\bootstrap\BootstrapAsset',
];
}
Make sure to register it in your module's views (you could use a custom layout) :
ModuleAsset::register($this);
Read more : http://www.yiiframework.com/doc-2.0/guide-structure-assets.html