Thứ Ba, 22 tháng 9, 2015

Using Yii2 Improved Application Templates

Installation


We start by running composer create-project command to download and install application template in our web root folder. Depending on your system setup, web root folder may be "htdocs", "public_html", "www", or like in my case "sites". So open your console and type command to change working directory to your web root folder, and there we will execute composer create-project command to install basic template, plus we will name our newly installed application "basic", very creative...

cd /var/www/sites/

composer create-project nenad/yii2-basic-template basic

Once download is complete, we are ready to move to our next step. Difference between improved basic template and the default one provided by core yii2 developers is that improved basic template has almost all features that default advanced does, plus it has few more. Because of this, improved basic template is using database out of the box. So our next step is to create database that we are going to use for our project, and then we need to update our application database configuration with proper credentials like database driver we are going to use ( if you are not using MySQL which is default ), database name and other.

Create database that you are going to use. I will use phpMyAdmin tool to create mine, and I will call it "basic".


Now in your text editor or IDE, open your application and update db.php configuration file located in_protected/config folder. Adjust your database credentials. I am fine with defaults.


Now we are ready for last 2 steps. First is to run yii migrations that will populate our empty database with tables that our application need in order to work. To learn more about migrations you can readmigrations guide. In your console, change directory to _protected, and execute yii migrations:

cd /basic/_protected/

./yii migrate

NOTE: if you are on Windows, you will run yii commands without this ./ in front of them, so just yiisome command...

Great, your migrations should be installed, and if you look at your database in some GUI tool, you should see 6 new tables. Now we are ready for our last step. Since both basic and advanced improved templates are using Role-based access control out of the box ( tables created with auth_prefix are RBAC ones ) we are going to use our RbacController ( located in console/controllers ) to insert some of our default roles and permissions to our RBAC tables. You can adjust everything in RbacController to fit your needs, and I will explain you that later, but for now let's use default implementation. While you are in _protected folder ( in your console ), execute this command that will invoke our RbacController's init action that will install our RBAC authorization data in database.

./yii rbac/init

You should see message: "Rbac authorization data are installed successfully."
That is it! Now you can open your application in localhost. Just visit in your URL:
localhost/basic

VERY IMPORTANT NOTE!!!: both improved templates are using pretty url and .htaccess out of the box to make our URLs short and pretty. If you are getting 404 errors you will have to enable mod_rewrite and AllowOverride All in your Apache configuration. These guides should help you:
Guide for Linux -  read sections 1 and 2. Guide for Windows

Application structure


Application structure in improved templates is different than in default ones.
First, this structure is more intuitive. Second, protected content is separated from the one that is publicly accessible. Third, we can move _protected folder outside the web root for improved security. Fourth, we do not need extra efforts to make our application look good (there is no web folder in your URL, you do not need redirection`s to achieve that), Fifth, theme folder has been added to templates in order to support theming out of the box.

Now you may wander why our _protected folder has this _ (underscore) in front of "protected". There are 2 reasons:

First is that underscore in name will push the folder to the top of our text editors / IDEs file managers, making convenient visual separation of protected folder from everything else.

Second reason is more important.
Lets say that you want to host more than one application on your server. Since it is good security practice to move protected content outside the web root, you will want to move _protected one level above web root. In my case I would put _protected in www folder since sites is my web root. Now, what if I have one more application and I want to move it's _protected folder too? Well, since we can not have two folders with same names in one place, we will have to rename them. In that situation it is a good practice to give your _protected folders same names of applications that these folders belong to, but keep this _ (underscore) to indicate that this is protected folder that belongs to that application.
For example if the name of my site is freetuts, I will move _protected folder outside the web root and give it a name of _freetuts. This way in case I have many folders in that place, I can easily visually identify _freetuts as a _protected folder of freetuts web site. Good practice that can prevent a lot of headache.

And last thing to note: in case you decide to move your _protected folder outside the web root, you will have to update your index.php entry script to point to that folder one level above ( plus if you rename it, don't forget to update that too ).

New features


It is time to start using our application and see what we got. Start it in your web browser. Once you open basic template in web browser you will notice 2 main differences comparing to default basic template. First, it looks different. That is because of "slate" theme that both improved templates are using by default ( more about theming in separate chapter ). Second, there are Signup and Articles options in our menu. Improved basic template has almost all features that default advanced does, plus it has some more. One of those features is user signup. Users will be saved in our database inuser table. Let's start from signup.

SIGNUP: first thing that you should know is that first user that will signup to our application will gettheCreator role ( this is how I call super admin ). If you look at our RbacController located in_protected/console/controllers, you will see that we will create 5 roles by invoking init action when we install template ( they will be inserted into auth_ tables ). Roles are: member, premium, support, admin and theCreator. You can read more about them in RbacController. First user that will signup to our application will be You, that is why first user will get theCreator role, because you are The Creator. Every other user after first one will get member role, which is just normal authenticated user.

By default, after you fill in signup form and registration is successfully finished you will be automatically logged into system ( go register yourself ). This is fine in some systems, but it is often very good idea to force users to activate their account using email activation system before they can login. This activation system is built into both basic and advanced improved templates, and to use it you just have to change "Registration Needs Activation" ( rna ) setting to true. Settings are located inconfig/params.php configuration file, so when I say "settings" in this guide, you should look there. Now if you try to sign up new user, you will see that activation is necessary.


There are 3 important things for you to know:

1. If you want to send email from your computer you need to have email server installed and properly configured. I can not guide you how to do this, because I do not have it on my machine.
2. If you are able to send email either from your local machine or hosting one, you will have to update mailer component in _protected/config/web, and set useFileTransport to false. If it is set to true Yii will fake sending email by writing them to files.
3. You can try registration with activation at my demo page. If you signup with your existing email you will receive activation email there.

LOGIN: if you visit params.php settings file again you will see that second setting is Login With Email. By default when user is trying to login, he should use his username/password combo, if you set lwe to true, he will have to use email/password combo. There is a debate in web development community which option is better. In my opinion it depends... This is why I have provided both options, so that you can chose what you want without having to write single line of code.

STRONG PASSWORDS: third setting option that you can use is Force Strong Password. When you was registering your account you probably saw that password strength meter is enabled by default. This is because it is a very good practice to guide your users to use passwords that are not easy to crack. And since strength meter is displaying their password strength, hopefully they will use a "better" password. In systems where you need higher security, it is also very good practice to force users to use strong passwords. How strong ? It depends... But by turning fsp option to true users of your application will have to use password with strength defined by the preset you chose. Default one is normal. For signup form you can change preset in SignupForm.php model insidepasswordStrengthRule() method. For user management form, visit User.php model. Presets are located in _protected/vendor/nenad/yii2-password-strength/presets.php. You can chose any of existing ones, or create new.

USERS: next feature is ability to manage users of our system. This option is very straightforward, just visit Users option in your menu when logged in as theCreator or admin. One important thing to know is that admins can not see The Creator in the users list ( they shouldn't mess with your account ), and they can not assign theCreator role to anyone. Only You should be able to assign this role.
Here is an image of me assigning admin role to the user with username of "admin":


This option to easily update user role is very convenient to have even if you are using RBAC module in your system. I will explain you RBAC in more detail in next section.

ARTICLES: starting from version 2.1.0, users with editor or higher role can create, update and delete articles, and everyone can view them. Article ( post ) is content that users of our system can create, and therefore it is considered to be dynamic content. In default hierarchy of roles that comes preinstalled with improved template, editors are the lowest user roles that can create and update their own articles. For example, if we have two editors in our system: John and Scott, John will not be able to update articles created by Scott and vice versa. Admin is the role above editor, and admin can do everything with articles, including updating and deleting all articles.
Here is an image of editor "John Doe" creating his first article:


RBAC: let's go!


First you should read the official yii2 guide for RBAC. Once you have some basic understanding what RBAC is, you are ready to learn how you can use it in improved templates.

I have already said that improved templates are using RBAC that is storing its authorization data in database out of the box. Also, we are using RbacController to create some basic roles , permissions and rules for our applications. We have 6 roles installed out of the box: member, premium, support, editor, admin and theCreator. All 6 roles are in the same hierarchy, where roles above inherit everything from the roles below.

Let me explain this further. We have our member role. This is just normal authenticated user that can use protected content of our site once he is logged in. Next is premium role. Premium is actually premium member, member that has some extra powers. For example he could get those powers by buying premium account, or maybe admin has decided to reward some loyal member with premium role so he can use some extra content that normal members can not. Next there issupport role. This role is for our site support staff, they can do everything that members and premium members can, plus you will want to assign some extra permissions to this role depending on your needs. Then comes editor role. Editors are responsible for creating articles ( and maybe some other dynamic content ) in your application. Now comes the admin role, this is our client, person who own the site and want to administer it, or he has someone who will do that for him. Here we can see our hierarchy on work. If you look at the code responsible for creating admin role, you will see that we have assigned editor role to admin. This means that admin can do everything that editor, support, premium and member can do. But even further, we have assigned some permission to admin that others do not have.

// add "admin" role and give this role: 
// manageUsers, updateArticle and deleteArticle permissions, plus he can do everything that editor role can do.
$admin = $auth->createRole('admin');
$admin->description = 'Administrator of this application';
$auth->add($admin);
$auth->addChild($admin, $editor);
$auth->addChild($admin, $manageUsers);
$auth->addChild($admin, $updateArticle);
$auth->addChild($admin, $deleteArticle);

Now I want you to know that I didn't have to create this manageUsers permission in order for template to work. Inside our template we are doing access checks by checking does some user has some particular role, like "admin". But these permissions may be needed in case your system grows larger and doing access check by permissions become more effective ( I will explain this in a moment ). Also this code serves well as a guide to you, how you can setup RBAC yourself. At last, there istheCreator role, this is you. You are able to do everything that admin can, plus you can assign additional permissions to yourself.

// add "theCreator" role ( this is you :) )
// You can do everything that admin can do plus more (if You decide so)
$theCreator = $auth->createRole('theCreator');
$theCreator->description = 'You!';
$auth->add($theCreator); 
$auth->addChild($theCreator, $admin);

In the code above you see that I have assigned editor role plus manageUsers permission to admin role. Once again I didn't have to create this manageUsers permission, our access check in our code will work since we are checking by role : "Is this user admin ? If he is, let him manageUsers. ". To see this applied in combat, open up AppController located in _protected/controllers folder. There you will see that we are using Access control filter in combination with RBAC. This is allowing us to centralize our RBAC access checks to one place because our UserController is inheriting AppController. If we would not do it like this, we would have to perform RBAC access checks on every method individually in our UserController and possibly all other that need RBAC. This is more effective way.

'rules' => [
    [
        'controllers' => ['user', 'article'],
        'actions' => ['index', 'view', 'create', 'update', 'delete', 'admin'],
        'allow' => true,
        'roles' => ['admin'],
    ],
    [
        'controllers' => ['article'],
        'actions' => ['create', 'update', 'admin'],
        'allow' => true,
        'roles' => ['editor'],
    ],
    [
        'controllers' => ['article'],
        'actions' => ['index', 'view'],
        'allow' => true
    ],
    [
        // other rules
    ],

], // rules

So I said that we do not really need permissions created by RbacController in order for our RBAC to do its job in templates.
But what if we want to have one more role that can manage users, and should not be related with existing 6 roles ?
Let's say that we want to have chuckNorris role who will have permission to manage users, and we want him to have only that option. Ok, no problem, we can create that role with this simple code:

$chuckNorris = $auth->createRole('chuckNorris');
$chuckNorris->description = 'He can just manage and nothing else!';
$auth->add($chuckNorris); 
$auth->addChild($chuckNorris, $manageUsers);

And to allow Chuck Norris role to use UserController we will have to create new rule in our AppController:

[
    'controllers' => ['user'],
    'actions' => ['index', 'view', create', 'update', 'delete'],
    'allow' => true,
    'roles' => ['chuckNorris'],
],

Now we have two rules defined for UserConroller. One saying that admin can use UserConroller, other that chuckNorris can do it too. Can we do this more effective ? Yes we can. Both admin and chuckNorris have manageUsers permission assigned to them. So lets create one rule that will check access by permission manageUsers, and since both admin and chuckNorris have manageUsers assigned to them they will both be able to use all actions of our UserController, and we will reduce amount of rules we need to write. Now we would need only this rule to get job done:

[
    'controllers' => ['user'],
    'actions' => ['index', 'view', 'create', 'update', 'delete'],
    'allow' => true,
    'roles' => ['manageUsers'],
],

Hopefully you realize now that permissions become a must once your application start to grow ( if you need to have a lot of different users with different powers ).

Last thing that I want to discuss in this section is when to use RBAC modules that allow you to create authorization data and assign them to users using GUI.

In Yii 1 there are several RBAC modules that you can install to your application, and they will allow you to create RBAC authorization data using GUI. This is nice and in large applications where you need to alow admins to manage RBAC, having GUI for that is a must because, most likely, administrators of that application are not programmers and it is more convenient. Also it is very important that RBAC GUI is easy to use and understand, because it would be pain in the but to explain how to use RBAC manager to not programmers. At the moment of this tutorial writing, I do not know about any good and well tested RBAC manager for Yii2. But I want you to realize that our RbacController will be enough for many of our applications. In many applications you will have fixed amount of roles and permissions so you will not need to provide RBAC manager to your clients, and therefore RbacController will be all that you need.

Advanced template


There are three main differences between advanced and basic template:
1) Advanced template has environments support out of box.
2) Advanced template is consisting from two applications: frontend and backend. Because of this advanced template also has different folder structure.
3) Improved advanced template is storing it's session data in database, while basic one is storing it in files located in runtime/session folder.

Let's install improved advanced template now. In your web root folder run this composer create-project command that will download nenad/yii2-advanced-template and rename it to advanced on the fly ( just to have prettier name ).

composer create-project nenad/yii2-advanced-template advanced

Now move to _protected folder and execute php init command that will initialize our application in either development or production environment. You will have to  chose 0 for development and typeyes to confirm.

cd advanced/_protected

php init

Now it is good time for you to create database that you are going to use. I will call mine advanced. Also, after you have initialized your application, you should adjust your database credentials in_protected/common/config/main-local.php. I am fine with defaults, but you go adjust your config.

Once we have database created and database configuration set, we have to execute yii migrationsand rbac/init like in basic template:

./yii migrate

./yii rbac/init

You are done!
In default advanced template to see frontend and backend parts of your application you would have to visit these URLs ( when pretty url and htaccess are installed ):
localhost/advanced/frontend/web and localhost/advanced/backend/web

But since improved advanced template has different structure, you will visit frontend and backend like this:

localhost/advanced

localhost/advanced/backend

You first question now may be: "When to use basic and when advanced template"?
Well this really depends on your needs. If your clients do not request from you to have application separated to backend and frontend you may decide to use basic template. But also, advanced template does bring "better" code and application structure so you may still decide to use advanced over basic template. As you can see the choice is only yours. I tend to use advanced template for almost all my applications, but that is just me....

ENVIRONMENTS: now let's discuss this environments thing smiley. I see that most people do not understand how to use it. Most of them are like: "Do not touch environments folder it is so scarry!". No it's not... I am going to explain you how to use it through real world example. Let's go.

Let's say that right now we want to deploy our advanced application on production server. Most likely you will have to use different database configuration for your production server. So you decide to change main-local.php file in common/config folder and enter your production database credentials there. You use FTP client to push your application to your production server, you use sql dump to insert all your local database data to your production database, and everything is cool. But now, your client request new feature from you, so you will have to develop it on local machine. This will mean that you will have to manually change your main-local.php config to enter your local database credentials, and once you are done you will have to enter your production credentials again. This is bad, and I hope that you see why. Do we really need to manually update all our configuration files whenever we want to do some changes and push them to production ? In this example we are just updating one file that is containing our database credentials, but what if we have more ? Use environments folder !

Open your environments folder. Yes open it! Buahahahahaha.


You will see that in environments folder we have dev and prod folders. They are representing our development and production configurations. If you run php init now and chose 1 for production, you will be asked to confirm file overwrites. And this is what scares people, what am I overwriting ? Well look in environments folder. Files that you find there will overwrite the same ones in application. So, how to use this ? If you open prod/_protected/common/config folder you will see main-local.php file that will overwrite the one that already exists in your application common/config folder. Well, why don't you specify there your production database settings ? And insidedev/_protected/common/config/main-local.php use settings for your development machine. Now if you run php init and chose 1 for production and allow it to overwrite files, you will get main-local.phpfile with your production database settings in your application. If you decide to use development one, just run php init again, chose 0, overwrite all, and you will get settings for your development machine.

So to summarize, you use environments folder to store your production/development application settings, and use php init command to chose what you want. Very simple, very handy.

Theming


In improved templates theming is working out of box. Here I will answer to some of the common questions like:
- How to configure which theme you want to use
- How to use different layout / views
- How to create your own theme

I will answer to these questions by providing examples while using advanced template.

CONFIG: Templates come with 4 themes out of the box, "default", "slate", "spacelab" and "cerulean". Since advanced template is consisting from frontend and backend applications, you need to chose which theme you want to use for frontend and which for backend. Themes for frontend application are located in your application root folder ( for example: advanced/themes ), and themes for backend app are located in application root/backend folder ( for example: advanced/backend/themes ).

To chose which theme to use for frontend application open main.php config file located in:_protected/frontend/config folder and adjust the view component configuration.

To chose which theme to use for backend application open main.php config file located in:_protected/backend/config folder and adjust the view component configuration. Let's say that for our backend app we want to use default theme. Our view config would look like this:

// here you can set theme used for your backend application 
// (template comes with 'default' and 'cool')
'view' => [
    'theme' => [
        'pathMap' => ['@app/views' => '@webroot/themes/default/views'],
        'baseUrl' => '@web/themes/default',
    ],
],

VIEWS: Let's say that you want to use different layout for your frontend cool theme. Since Yii is searching for our view files in themes folder first, all we have to do is to create same view structure in our theme folder like we have in our application. So in this case, you would create view folder inside slate folder, and inside view folder you would create layouts folder and put your layout file there. You will have to call your layout main.php, so it is a good idea to copy the one from_protected/frontend/views/layouts folder and adjust it to your needs. And if you want, for example, to override index view of site controller, you would create site folder inside views folder, and put your index.php file there.

Your final structure may look like this:

CRAFTING: I said that I am going to show you how to create themes. Well I lied a little bit. I am not really going to teach you how to create themes, that is out of scope of this tutorial, but I will give you few tips.

Here are two possible ways of creating your custom theme:
1. You just want to override some default bootstrap css style like I did in default theme.
2. You want to override all bootstrap css styles. In this case you would tell Yii not to load default boostrap.css file from our server, because you will use your version that have everything you need. This is done with "slate", "spacelab" and "cerulean" themes.

Either you chose to use these 2 approaches or something third, I recommend you to include site.cssfile in your theme like I did in all themes. So you will have one file representing bootstrap theme, and site.css that is containing system specific styles. You can merge them, import boostrap theme in site.css, whatever... But it is important to have these styles from site.css, at least some of them. You can experiment, modify... But note that some styles like this one :

/* hide strength meter so we can fade it in nicely with jQuery */
.nz-meter-container {
    display: none;
}

are needed for some of our application extensions to work as intended. Have fun.

 

Translation


Starting from version 2.1.0, improved templates come translation ready. This means that all application messages and interface text are wraped with Yii translation helper method, that allows you to translate the given text easily:

Yii::t('app', 'Some text that needs to be translated')

Even further, templates will come with Serbian ( sr ) translation installed, so you can use it as a guide to create your language translation. Application source language is English, so you will be translating English text to your language like I did when creating Serbian translation. In basic template translations are located in _protected/translations folder, and in advanced template it is_protected/common/translations.
Instead of copy/pasting your translations to templates every time you download them for your new project, you can create a pull request on Github with your native language translations, and I will add them to templates. 


Running tests


Yii2 application templates are using Codeception for testing code. I am not going to teach you how to test your code or how to use Codeception ( I can do that in different tutorial ), I am just going to tell you what you need to do to run tests that are already written. If you have tried to run tests in default basic and advanced templates you probably saw that to be able to run unit tests you first have to install Codeception Specify and Verify libraries. Also since some of the tests are writing emails to files in runtime/mail folder, you may need to make mail folder writable first. In improved templates all of that is handled out of the box, you don't have to do anything.

If you want to run tests you should create additional database that will be used to store your testing data. Usually testing database will have the same structure like the production one. I am assuming that you have Codeception installed globally, and that you know how to use it. Here is how you can set up everything easily:

1) Let's say that you have created database called advanced. Go create the testing one called advanced_tests.

2) Inside your common/config/main-local.php config file change database that you are going to use toadvanced_tests.

3) Open up your console and cd to the _protected folder of your application.

4) Run the migrations that will populate our advanced_tests database:

./yii migrate 

5) Run rbac/init:

./yii rbac/init

6) Now you can tell your application to use your advanced database again instead of advanced_tests. Adjust your main-local.php config file again.

7) Now you are ready to tell Codeception to use advanced_tests database.

Inside: _protected/tests/codeception/config/config.php file tell your db to use advanced_testsdatabase.

8) Start your php server inside the root of your application (advanced folder):

php -S localhost:8080

9) To run tests written for frontend side of your application cd to_protected/tests/codeception/frontend , run codecept build and then run your tests.

10) Take similar steps like in step 9 for backend and common tests.

For basic template you can read instructions on the extensions page here.

Here is my terminal output after running backend tests:


Final tips


Where to go from here ? First I recommend you to read The Guide. Even if you already did it once, now after this tutorial I think that everything in this guide will make more sense, and you will be able to fill the gaps in your knowledge.

Yii2 framework API documentation is very important and useful resource. If you haven't used it so far, I highly recommend you to start using it. Bookmark it and keep it open while you do programming. If you do not know how to use some Yii class, which properties you can configure... this is the place to look.

If you are not testing your code, you should start. Google for Codeception testing tutorials. There are few good ones for other frameworks that will serve you well, but they are not free :-( .

After that just start doing stuff. If you are really stuck and have some problem ask on forum.

If you are Linux user I recommend you to read tutorial about creating and using terminal aliaseshere on freetuts.org. Aliases will help you to type less in terminal.

At the end I want to inform you that I will start working on new awesome template soon, and it will be based on improved advanced template. There will be new tutorials too. To be updated, it is best for you to follow us on Twitter.

Thank you for reading this tutorial, I hope it was useful to you, and thank you for using my application templates. Welcome to world of Yii, and see you next time.


EmoticonEmoticon