📜 ⬆️ ⬇️

Getting to know Yii 2 through creating a simple blog.

Hello, dear users!

As you already understood from the title, this article will discuss the new version of Yii. I will try briefly, on a live example, to introduce you to the wonderful Yii 2.

Writing a complete instructions for creating a blog probably does not make sense, since many steps are similar to the first version, but I will write exactly about the nuances that are different, and I will focus on the Yii2 updates that I noticed during the creation of the application. All the rest, you can quickly see in the demo application , which probably will be more effective than just written text.

Highlights


In Yii2, as you have already noticed, everything is built on the namespace, this is probably the main highlight of the new version.
Also a very important point: the “C” prefix from the file names has been removed.
')

Install and create the first application


We will use the basic application as a basis.
How to install it is very well described on Github on this immediately go to the following points.

Application structure


For example, I chose a modular structure. This will allow us to learn and understand the principle of the modules in Yii2.
So, in order to implement such a structure, we, as in the first version, need to create the main folder of all modules “modules”, in which we will create separate folders for individual modules. It's all like in the first version.

The only thing that has changed in the modules is the name of the main class of the module. As I understand it, it is no longer necessary to write the “Module” suffix, so our main files will have clear names without a suffix.

Example:
Site.php, Users.php, Blogs.php, etc.
You can look at the structure already on the finished example, and it does not make sense to dwell on this anymore.

Application Setup: config / main.php


As in Yii 1.0, the application is configured through the main.php file, and many elements remain unchanged, but there are still many parameters that have been renamed, which should be remembered if the application does not work after configuration.

Some examples of such changes and features:

In case of inoperability of any parameters, you can easily peep everything in the source code of the frame.
As soon as we set up our application and connected our modules, we can start writing our “CRUD”.

CRUD


A detailed example is in the demo code, but, to be honest, there is no strong difference from the first version. The only thing that has appeared is the controller method: populate (), which was recently transferred to the model and renamed to load ().

Example:
 public function actionCreate() { $model = new Blog(); if ($model->load($_POST) && $model->save()) { return Yii::$app->response->redirect(array('view', 'id' => $model->id)); } else { echo $this->render('create', array('model' => $model)); } } 

 $model->load($_POST) //    if (isset($_POST['Blog'])) { $model->attributes = $_POST['Blog']; } 

There are no other special differences in working with CRUD.

Model


The main innovation is the “scenarios ()” method by which you can set up model validators depending on the specified scenario.
 public function scenarios() { return array( 'backend' => array('email', 'role'), 'frontend' => array('email', '!name'), ); } 

The model binding is done by the formName () function which ultimately returns the name of the Model Class to which the form belongs.
Also an important point - model () was removed, and now the work with the model is happening, as well as with another regular class:
  MyModel::getAuthor(); 

ActiveRecord


Everything has been rewritten, now in Yii2 a new AR, which really pleases.

Examples of several innovations:
"Scopes ()" were replaced by the usual methods of the AR model, which now look like this:
 public function active($query) { return $query->andWhere('status = ' . self::STATUS_ACTIVE); } 

Also, “relations ()” were radically changed, which are now defined as heterologues, which is more correct. Two types of relations are available: “hasOne ()”, “hasMany ()”.
 public function getAuthor() { return $this->hasOne('app\modules\users\models\User', array('id' => 'author_id')); //   –     ,     . //          PK  (id)  FK     (author_id),     } 

Also, the functions of sampling from the database were rewritten, and added with new ones.
 $customers = Customer::find() ->where(array('status' => $active)) ->orderBy('id') ->all(); // return the customer whose PK is 1 $customer = Customer::find(1); $customers = Customer::find(array('status'=>$active)); $customers = Customer::find()->asArray()->all(); $customers = Customer::find()->active()->asArray()->all(); 

Finally, AR now automatically binds the model to the database, due to the “tableName ()” function, which by default returns such a value “tbl_MODEL_NAME”. For example, the “User” model will be tied to the “tbl_user” table. If the table name is different, you can simply override the function.

Developments


In the new version, working with events has become as simple as possible. In the demo application, I gave an example of my own event - when adding a new user, the event is called in afterSave (), although there you can use standard events that are available in Yii, such as “EVENT_AFTER_INSERT”.

In order to define an event, it is enough to call the “trigger ()” function in the right place, and only then in the right place to set an event handler for the event.

Example:
  app\modules\users\models\User ... public function afterSave($insert) { //   $event = new ModelEvent; $this->trigger(self::EVENT_NEW_USER, $event); parent::afterSave($insert); } ...  app\modules\users\controllers\DefaultController ... public function actionSignup() { $model = new User(); $model->scenario = 'signup'; if ($model->load($_POST)) { if (!$this->module->activeAfterRegistration) //    ,   [[EVENT_NEW_USER]] $model->on($model::EVENT_NEW_USER, array($this->module, 'onNewUser')); if ($model->save()) { Yii::$app->session->setFlash('success'); return Yii::$app->response->refresh(); } } else { echo $this->render('signup', array('model' => $model)); } } ... 

There are several ways to bind a handler:
 function ($event) { ... } //   array($object, 'handleClick') // $object->handleClick() array('Page', 'handleClick') // Page::handleClick() 'handleClick' //   handleClick() 

View


In Yii2, a new class has emerged that is responsible for all the views of the application, and which performs the output directly.
Now in the view files, the variable "$ this" refers not to the controller, but to the new class "yii \ base \ View".
In order to call a specific function of the controller or widget to which the view belongs, you need to refer to the method: "context".

Example:
 //  app\modules\blogs\views\default\index // $this->context    app\modules\blogs\controllers\DefaultController //    ,       echo $this->context->module->recordsPerPage; //  10 // app\modules\comments\widgets\comments\views\index // $this->context    app\modules\comments\widgets\comments\Comments if ($this->context->model['id'] == 10 ) {...} 

Widgets


Widgets have been supplemented with new methods, plus now they should be directly output via “echo”.

Example:
 // Note that you have to "echo" the result to display it echo \yii\widgets\Menu::widget(array('items' => $items)); // Passing an array to initialize the object properties $form = \yii\widgets\ActiveForm::begin(array( 'options' => array('class' => 'form-horizontal'), 'fieldConfig' => array('inputOptions' => array('class' => 'input-xlarge')), )); ... form inputs here ... \yii\widgets\ActiveForm::end(); 

Action filters


In the new version, the controller filters are implemented as “behaviors”.
 public function behaviors() { return array( 'access' => array( 'class' => \yii\web\AccessControl::className(), 'rules' => array( // allow authenticated users array( 'allow' => true, 'actions' => array('login', 'signup', 'activation'), 'roles' => array('?') ), array( 'allow' => true, 'actions' => array('logout'), 'roles' => array('@') ), array( 'allow' => true, 'actions' => array('index', 'view'), 'roles' => array('guest') ), array( 'allow' => true, 'actions' => array('edit', 'delete'), 'roles' => array('@') ), // deny all -   ,      array( 'allow' => false ) ) ) ); } 

Small nuance - only 2 roles left out of the box:

Static helpers


Many new helpers have been added to Yii2. For example, like the same SecurityHelper, which speeds up work with passwords and generated codes, ArrayHelper, Html, and others, which again pleases.

Activeform


Forms are now created even faster and more conveniently, due to the ActiveField class, which simplifies the style of writing code, which is good news.
 <?php $form = ActiveForm::begin(array('options' => array('class' => 'form-horizontal'))); echo $form->field($model, 'username')->textInput($model->isNewRecord ? array() : array('readonly' => true)); echo $form->field($model, 'email')->textInput(); if (!$model->isNewRecord) { if (Yii::$app->user->checkAccess('editProfile')) { echo $form->field($model, 'status')->dropDownList(array( User::STATUS_ACTIVE => 'Active', User::STATUS_INACTIVE => 'Inactive', User::STATUS_DELETED => 'Deleted' )); echo $form->field($model, 'role')->dropDownList(array( User::ROLE_USER => 'User', User::ROLE_ADMIN => 'Admin' )); } echo $form->field($model, 'oldpassword')->passwordInput(); } echo $form->field($model, 'password')->passwordInput(); echo $form->field($model, 'repassword')->passwordInput(); ?> <div class="form-actions"> <?php echo Html::submitButton($model->isNewRecord ? 'Register' : 'Update', array('class' => 'btn btn-primary')); ?> </div> <?php ActiveForm::end(); ?> 

User and Identity


The user robots are now implemented through the “yii \ web \ User” class and the “yii \ web \ Identity” interface, which is more flexible to use.
Because of these changes, user attributes can be obtained through the user’s “identity” method.

Example:
 echo Yii::$app->user->identity->username; 

URL Management


There are slightly modified styles of writing rules.

Example:
 ... array( 'dashboard' => 'site/index', 'PUT post/<id:\d+>' => 'post/update', 'POST,PUT post/index' => 'post/create', 'POST <controller:\w+>s' => '<controller>/create', '<controller:\w+>s' => '<controller>/index', 'PUT <controller:\w+>/<id:\d+>' => '<controller>/update', 'DELETE <controller:\w+>/<id:\d+>' => '<controller>/delete', '<controller:\w+>/<id:\d+>' => '<controller>/view', ); ... 

RBAC


Working with user rights is now available initially from the box without adding your code, as, for example, in the case of using the file variant in the first version.
Below I will write a short instruction on RBAC and a description of the roles in the file.

First we need to create our own class, which will be inherited from "\ yii \ rbac \ PhpManager".
In our example, it is located in the “rbac” module in the “components” folder called “PhpManager.php”.
The code in it is simple. We simply set the path to our file with the described roles, and bind the user to the desired role.
 <?php namespace app\modules\rbac\components; use Yii; class PhpManager extends \yii\rbac\PhpManager { public function init() { if ($this->authFile === NULL) $this->authFile = Yii::getAlias('@app/modules/rbac/components/rbac') . '.php'; parent::init(); if (!Yii::$app->user->isGuest) $this->assign(Yii::$app->user->identity->id, Yii::$app->user->identity->role); } } 

After that, in the same folder we create the file “rbac.php” where we describe the roles we need. (The code can be seen in the demo application in the folder: @app/modules/rbac/components/rbac )

And finally, we just need to configure the “authManager” in the configuration file:
 ... 'authManager' => array( 'class' => 'app\modules\rbac\components\PhpManager', 'defaultRoles' => array('guest'), ), ... 

After that, in the right place for us, we can safely do checks of the user for the necessary rights:
 if (Yii::$app->user->checkAccess('editOwnBlog', array('blog' => $model)) || Yii::$app->user->checkAccess('editBlog')) { ... } 

This is all that I managed to find out, but I am sure that there was still a lot of things that did not happen.

At the moment, I did not have time to deal with ajax requests in Yii 2, namely, how to correctly create the necessary answer during model validation. In 1.0, it is done like this:
 echo CActiveForm::validate($model); 

if anyone already knows, write, sure many will be interested.

Total


Despite the still unfinished look, Yii 2 already looks very good. I am sure that only the best is waiting for us.

Yii 2 himself really liked. To be honest, there is already a great desire to start writing working projects on the new version, although this is still very early.

The article turned out great, but in another way just do not know how.

Thank you all for your attention. Good luck!

Demo blog on github. Installation instructions present.
Working example of a blog.

Source: https://habr.com/ru/post/185236/


All Articles