This is a template for the Yii 2 advanced application which I have decided to release.
But why?
Maybe it will help someone.
This template was born out of a number of a projects, including an e-commerce site. Covering a common set of functionality I kept implementing between them.
I also seemed to always do this very repetitively as such I sought to remedy that. It incorporates what I, personally, feel is a good structure.
First I will talk abut the structure and then I will delve into the things I have done. I will attempt to explain it concisely however, it is likely I may miss things out.
This guide is intended for those who already know Yii 2 and the structure of a normal advanced application. If you are not one of those individuals please investigate the advanced application readme first.
common
components/ contains all of the extended components of the framework
config/ contains shared configurations
mail/ contains view/template files for e-mails
rbac/ contains the role based permissions configuration
models/ contains model classes used in both backend and frontend
tests/ contains various tests for objects that are common among applications
widgets/ contains widgets common to both back and front end
console
config/ contains console configurations
controllers/ contains console controllers (commands)
migrations/ contains database migrations
models/ contains console-specific model classes
runtime/ contains files generated during runtime
tests/ contains various tests for the console application
backend
assets/ contains application assets such as JavaScript and CSS
config/ contains backend configurations
controllers/ contains Web controller classes
models/ contains backend-specific model classes (Does not actually exist)
runtime/ contains files generated during runtime
tests/ contains various tests for the backend application
views/ contains view files for the Web application
web/ contains the entry script and Web resources
frontend
assets/ contains application assets such as JavaScript and CSS
config/ contains frontend configurations
controllers/ contains Web controller classes
models/ contains frontend-specific model classes (Does not actually exist)
runtime/ contains files generated during runtime
tests/ contains various tests for the frontend application
views/ contains view files for the Web application
web/ contains the entry script and Web resources
vendor/ contains dependent 3rd-party packages
environments/ contains environment-based overrides
The directory structure has changed a little to a version that I have tested as being quite good. The main changes revolve around moving stuff to the common/
folder. common/
holds all of the stuff that is common to the application globally.
components/
holds all of the extended Yii 2 components such as custom Controller
, User
and Request
objects.
You can put extensions in here but you may find it better to put them in an extensions/
folder, it is entirely up to your better judgement.
This folder contains all the stuff for mail, from templates to view files.
The mail templates and views are strictly global to the entire application.
This folder contains the RBAC configuration including rule classes.
Again this is global across the entire application.
I have made all models reside in common/models
including the SignupForm.php
, PasswordResetRequestForm.php
and the ResetPasswordForm.php
.
The reason for adding even these, normally frontend, models is because I found more and more that they are also useful on the backend. You want employees of a company using the backend to be able to register and reset their passwords without having to jump between two systems; especially if they are a new employee on their first day of work registering a new account in your system.
This means that the models/
folder in both backend and frontend do not actually exist, but they can if you really need them to.
This folder contains global widgets.
There are a number of widgets you may find are actually global to your entire application, for example: I have already added the Alert
widget as a global widget and added it to both the frontend and the backend layout.
Now moved to common/models
.
Now moved to common/models
.
Composer has been changed. What it installs by default has been expanded and/or changed.
By default, Composer will download the MongoDB extension. I will explain later how to rid it of that, it is literally 3 lines of changes.
Here is a brief but comprehensive list of changes in composer:
yii2-mongodb
has been added and is the default database of the applicationyii2-jui
extension has been addedyii2-imagine
has been added for image manipulation capabilitiesIt is important to get to grips with the configuration and how it is laid out before you start fiddling.
Most of the configuration is placed within common/config/main.php
however a sizeable amount of customisation exists within backend/config/main.php
and frontend/config/main.php
.
The common/config/main.php
contains:
The asset manager configuration provides the ability to have a custom Bootstrap with your own theme and CSS for it.
The RBAC configuration allows for the default RBAC that is set-up in this template, refer to the RBAC section below.
The other parts are not so important and do pretty much what they say on the tin. Ensure to take a good long look at the configuration files and also the params.php
files within those directories.
The params.php
files tends to hold varibles which are helpful. These files are quite bare currently so do not be surprised if you hear nothing of them again.
Some of the configuration is defined within the environments folder too, essentially the database, for example: SQL and MongoDB are both defined in the environments folder's own configuration files.
All controllers now inherit from common\components\Controller
which provides tier 2 functionality and SSL redirects, which will be discussed later.
The common\components\Controller
class runs a beforeAction
event which can be expanded with your own functionality.
I found more and more that in a real production environment CSRFs on every action were causing problems, especially on e-commerce sites. Mainly the problems revolved around the fact that not everyone posted to the website with CSRF tokens, especially if they came in from marketing campaigns such as Google AdWords or emails.
As time went on I found I actually wanted to disable CSRF by default but then enable it on pages that could be potentially insecure.
This is more fine grain than disabling CSRF on entire controllers which is currently the only other option.
An example taken from frontend/config/main.php
:
'request' => [
'class' => 'common\components\Request',
'enableCsrfValidation' => true,
'csrfRoutes' => [
'site/login',
'site/signup',
'site/request-password-reset',
'site/reset-password',
'site/confirm-login'
]
],
The above will make the CSRF work only on those routes. It is important to also define enableCsrfValidation
to ensure it works within Yii 2 itself.
When your site cannot entirely run over SSL you may wish to define certain routes as SSL only, for example: with this template you may wish to define that site/login
, site/signup
and user/index
are SSL routes.
Just like above, for CSRF routes, you can define these by filling a property of sslRoutes
in your request configuration with route paths.
The SSL route will be redirected within the common\components\Controller
beforeAction
event.
Tier 2 logins can be very helpful for e-commerce sites that wish to keep the user logged in but do not wish to leave them with he ability to order items without being securely logged in.
You will see an example of this on your local Amazon site, in my case Amazon.co.uk. It will keep you logged in but when you try and buy something it will ask you for your password.
These logins are disabled on the backend by default but enabled on the frontend via the configuration in frontend/config/main.php
:
'user' => [
'enableTier2' => true,
'tier2Timeout' => 3600 /* 10 mins */
]
As you can see the configuration is applied to the user object. By default the user component in this application template is common\components\User
.
When you login it will set a session variable with the time out (here 10 minutes by default) and that time out will continue to grow provided you keep browsing the site within the specified time frame (in this case 10 minutes).
When a user is inactive for longer than 10 minutes it will continue to keep them logged in and allow them to do certain actions but if they hit an action which you have defined as being tier 2 they will be asked to login.
For example within the frontend/controllers/UserController.php
file you might have:
public function behaviors()
{
return [
'access' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['subscribe'],
'roles' => ['?']
],
[
'allow' => true,
'actions' => ['index', 'recent-orders', 'change-password'],
'roles' => ['tier2User']
],
[
'allow' => true,
'roles' => ['user']
],
],
],
];
}
The tier2User
role relates to RBAC and runs the rule at common/rbac/Tier2Rule.php
.
If the user is found to not be tier 2 logged they are redirected to site/confirm-login
.
The RBAC that is in place is done via the common\components\PhpManager
and essentially works by adding a role field to a user which contains a role.
This role is then linked to the common/rbac/items.php
file and can include inheritance from other roles.
I found this style of RBAC to apply to many sites easily, without much effort, even e-commerce sites.
The RBAC that comes with this application template has six roles:
The default role applied to all new users will be user
and it will be saved as full text within the record, like so (taken from MongoDBB):
{ "_id" : ObjectId("543e94856803fab5038b4570"), "username" : "sammaye", "status" : NumberLong(10), "role" : "user", "created_at" : NumberLong(1413387397), "updated_at" : NumberLong(1413394841) }
The default role applied to any non-logged in user of your site will be guest
.
Both frontend and backend have their own Bootstrap contained within their respective web
folder.
I find this the best option since I always want to apply my own variables and themes to Bootstrap as such it makes perfect sense that you should have control over it.
This is facilitated by the configuration within the common/config/main.php
file:
'assetManager' => [
'bundles' => [
'yii\bootstrap\BootstrapAsset' => [
'basePath' => '@webroot',
'baseUrl' => '@web',
'sourcePath' => null,
],
'yii\bootstrap\BootstrapPluginAsset' => [
'basePath' => '@webroot',
'baseUrl' => '@web',
'sourcePath' => null,
]
],
]
and also exists within the asset compressor configuration file.
Within the frontend/config/assets.php
is placed an example file which will work with the assets compressor command to allow you to compress your assets.
This will in turn compress to the specification defined within the common/wigets/AllAssets.php
file.
I have changed the login form to work by email address instead of username. This seems far more appropiate for many sites where quite a lot of time you don't actually take a username.
All of the user normal user functions of:
exist in both frontend and backend. As stated above in the "common/models` section I have found time and time again I want these in both backend and frontend, not just frontend.
You can easily remove MongoDB from this template by removing the extension line from composer and then running:
php ./composer.phar update
after which, "grep"-ing for yii/mongodb/ActiveRecord
and replacing it with yii/db/ActiveRecord
.
No stable releases.
Comments