Yii v2 for beginners

You are viewing revision #35 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.

« previous (#34)next (#36) »

  1. Intro
  2. Prerequisities
  3. Yii demo app + GitLab
  4. User management + basic SQL commands
  5. Login via database + Session
  6. Access rights

Please give me a few days to add whole text

Intro

Skip this paragraph if you are in hurry :-) ... 8 years ago I started these two tutorials for Yii 1:

... and today I am beginning with Yii 2 so I will also gather my snippets and publish them here so we all can quickly setup the yii-basic-demo.

I have some experiences with Yii 1, but I havent used Yii for almost 5 years so many things are new for me again. Plus I was suprised that the Yii 2 demo application does not contain some basic functionalities (like DB login, translations etc) which must be implemented in the most of web projects so I will focus on them. Plus I will talk about GitLab.

Prerequisities

Skip this paragraph if you know how to run your Yii demo project...

I work with Win10 + XAMPP Server so I will expect this configuration. Do not forget to start the server and enable Apache + MySQL in the dialog. Then test that following 2 URLs work for you

You should also download the Yii basic demo application and place it into the htdocs folder. In my case it is here:

  • C:\xampp\htdocs

And your index.php should be here:

  • C:\xampp\htdocs\basic\web\index.php

If you set thing correcly up, following URL will open your demo application. Now it will probably throw an exception:

The Exception is removed by enterinng any text into attribute 'cookieValidationKey' in file:

  • C:\xampp\htdocs\basic\config\web.php

Dont forget to connect Yii to the DB. It is done in file:

  • C:\xampp\htdocs\basic\config\db.php

... but it should work out of the box if you use DB name "yii2basic" which is used below ...

Yii demo app + GitLab

... text ...

User management + basic SQL commands

To create DB with users, use following command. I recommend charset utf8_unicode_ci (or utf8mb4_unicode_ci) as it allows you to use more international characters.

CREATE DATABASE IF NOT EXISTS `yii2basic` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `user` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(45) NOT NULL,
  `password` VARCHAR(60) NOT NULL,
  `email`    VARCHAR(60) NOT NULL,
  `authKey`  VARCHAR(60),
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

INSERT INTO `user` (`id`, `username`, `password`, `authKey`) VALUES (NULL, 'user01', '0497fe4d674fe37194a6fcb08913e596ef6a307f', NULL);

If you must use MyISAM instead of InnoDB, just change the word InnoDB into MYISAM.

Then use GII to generate model, views and controller. The GII URL will probably be

  • http://localhost/basic/web/index.php?r=gii.
  • When creating the model, check this checkbox: Enable I18N ... we will need i18n later
  • Note that there already is a model named User in the demo app. You will not need it if you want to use login-via-DB so feel free to check "Overwrite" in GII. The newly created User model will now be usable only for table operations, not for login. But we will enhance it, keep reading.
  • The new model will only have 3 methods: tableName(), rules(), attributeLabels()
  • In order to use the DB for login, we need to implement IdentityInterface which requires 5 new methods. But as I do not need all those methods, in some of them I have commented out their body in the example below.

The final model should look like this:

<?php

namespace app\models;

use Yii;

class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {

    // When user detail is being edited we will only modify attribute password_new
    // Why? We dont want to load password-hash from DB and display it to the user
    // We only want him to see empty field and if it is filled in, password is changed on background
    public $password_new;
    public $password_new_repeat;

    // ----- Default 3 model-methods by GII:
    
    public static function tableName() {
        return 'user';
    }

    public function rules() {
        return [
            [['username', 'email'], 'required'],
            [['username', 'email'], 'string', 'max' => 45],
            ['email', 'email'],
            [['password', 'authKey'], 'string', 'max' => 60],
            [['password_new_repeat', 'password_new'], 'safe'],
            ['password_new_repeat', 'compare', 'operator' => '==', 'compareAttribute' => 'password_new'],
            ['password', 'setPasswordWhenChanged'],
        ];
    }

    public function attributeLabels() {
        return [
            'id' => Yii::t('app', 'ID'),
            'username' => Yii::t('app', 'Username'),
            'password' => Yii::t('app', 'Password'),
            'password_new' => Yii::t('app', 'New password'),
            'password_new_repeat' => Yii::t('app', 'Repeat new password'),
            'authKey' => Yii::t('app', 'Auth Key'),
            'email' => Yii::t('app', 'Email'),
        ];
    }

    // ----- Password validator
    
    public function setPasswordWhenChanged($attribute_name, $params) {
        
        if (trim($this->password_new_repeat) === "") {
            return true;
        }
        
        if ($this->password_new_repeat === $this->password_new) {
            $this->password = sha1($this->password_new_repeat);
        }
        
        return true;
    }
    
    // ----- IdentityInterface methods:

    public static function findIdentity($id) {
        return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null) {
        return static::findOne(['access_token' => $token]);
    }

    public function getId() {
        return $this->id;
    }

    public function getAuthKey() {
        return $this->authKey;
    }

    public function validateAuthKey($authKey) {
        return $this->authKey === $authKey;
    }

    // ----- Because of default LoginForm:

    public static function findByUsername($username) {
        return static::findOne(['username' => $username]);
    }

    public function validatePassword($password) {
        return $this->password === sha1($password);
    }

}

Login via database + Session

... text ...

Access rights

... text ...