Although everyone’s programming style is different, some suggestions can make your code more standard and stable. The following points are summarized in this website update, hoping to help you learn and use Yii2.

The environment that

  • Server environment: CentOS
  • Development environment and IDE: MAC & PHPStorm
  • Yii: v2.0.15 base version

Next up

Before the development of

First, let’s talk about things before development. We will configure YiI2 to a state that is easiest to develop.

Composer

In addition to making it easier to install Yii2 and third-party extensions, being able to use Composer means that your server can at least run PHP-CLI. Then you can use the YII command line, which will bring endless traversal to your development.

For Composer, there are some key words that you should pay special attention to: install, update, require.

cultural

When yii2 is installed by default, the relevant information of the program is in English. The first step is to change it to Chinese, which is very simple.

// config/web.php
'language'= >'zh-CN'
Copy the code

Static cache problem

When using Yii2, we used to manage static files (images, CSS files, JS files, etc.) in resource classes. However, there may be browser cache problems, which can be avoided through configuration during development, especially when developing mobile pages.

// config/web.php
'assetManager'= > ['appendTimestamp'= >true].Copy the code

Configure the DB

Although Yii2 is database friendly, especially mysql, we should still use a stable and higher version. Not to mention that your application will not have a mobile terminal in the future, choosing an emoji-supporting database early on will prevent us from downloading a third-party library to solve the error problem.

If you can

  • Mysql5.3.3 +
  • The config/db. PHP charset = utf8mb4

Configure the debug

If possible, configure a PHP extension similar to XDEBUG and integrate it into your IDE. You will inevitably encounter bugs that are difficult to catch during the development process. This requires you to continuously observe the values and assignment paths of certain variables during the life cycle of yiI2. For specific configuration, please refer to my previous course, using Xdebug to support yiI2 debugging – PhpStorm configuration

Of course, Yii2’s own debug extension is also extremely useful, especially when configuring urlManager.

The development of

Here are some of my habits and tips for yiI2 development that I hope will prove useful to you.

Single responsibility

A class and a method should have only one responsibility, as shown in the following code

function getFullName(a){
    $isAdmin = Administrator::find()->where(['user_id'= >$this->id])->one();
    if($isAdmin && $this->xxx == 1) {return $this->first_name . "" . $this->last_name; }}Copy the code

For example, in the case above, it would be best to separate out the judgment about being an administrator, as follows

function getFullName(a){
    
    if($this->isAdmin() && $this->xxx == 1) {return $this->first_name . "" . $this->last_name; }}function isAdmin(a){
    return Administrator::find()->one();
}
Copy the code

Each approach is a minimal problem solving unit, for which you can read refactoring – Improving Existing Code, a book he read about three years ago.

The importance of models

A lot of yii2 beginners like to write a lot of logic into the actions of the controller. This is not correct. Our focus should be on the model, and the controller is only the input and output.

Let’s take associations for example. The following code is bad.

// A controller
public function actionIndex(a){
    // There is more code here.// Get the order set of a member from three days ago
	$order = Order::find()->where(["user_id"=>$userId])->andWhere([">"."created_at",strtotime(date("Y-m-d",time()))- 86400.*3])->all();    
}
Copy the code

It is best to put this logic into the membership model

/ / User model
public function recent3DaysOrders(a){
    return Order::find()->where(["user_id"= >$this->id])->andWhere([">"."created_at",strtotime(date("Y-m-d",time()))- 86400.*3])->all();
}

// In the controller
public function actionIndex(a){
    $order = $user->recent3DaysOrders();
}
Copy the code

The controller code strives to be simple, doing only basic input selection and output rendering.

The rules

Right and wrong, don’t write casually.

// Action of a controller
public function actionCreate(a){
    $model = new User();
    if(Yii::$app->request->isPost){
        $model->load(Yii::$app->request->post());
        if($model->xxx == xxxx){
            // todo
        }
        if($model->save()){
            //}}}Copy the code

The code above is very familiar, and this is what we expect, but sometimes the input is not as honest as it should be, and we need to do more validation. Please do not write validation directly into the action, such as the if judgment in the code above.

** Leave validation to the rules and scenarios of the model. * * all.

Always think of reuse (small widgets)

The principle of coding is to reuse as much code as possible, especially widgets, which allow reuse in the view layer, widgets are very easy to use

Create a “Components” folder under @app

Create a Widget class in components (must inherit from yII \ Base \Widget)

3. Render a small widget view (under Components/Views if needed)

4. Use it

Don’t get it? Let me give you an example.

// components/Top10.php

      
namespace app\components;

use yii\base\Widget;
class Top10 extends Widget {


    public function init(a){
        parent::init();
    }

    public function run(a){
        parent::run();

        return $this->render('top10'); }}Copy the code

Write a view

// components/views/top10.php
<h1>Hello Top10</h1>
Copy the code

Use it

// A view
<?= \app\components\Top10::widget();? >
Copy the code

Widgets can be complex, such as ActiveForm, GridView, and so on. I also wrote an article about small pendants before, if you are interested, you can read it. portal

Be careful with AR associated loops

The problem, as I mentioned in the previous video, is lazy loading versus instant loading. For example, the following code is not good

$customers = Customer::find()->limit(100)->all();

foreach ($customers as $customer) {
    // SELECT * FROM `order` WHERE `customer_id` = ...
    $orders = $customer->orders;
}
Copy the code

The above code executed 101 queries. What if there was more data? Here’s how we solved the above problem.

// SELECT * FROM `customer` LIMIT 100;
// SELECT * FROM `orders` WHERE `customer_id` IN (...)
$customers = Customer::find()
    ->with('orders')
    ->limit(100)
    ->all();

foreach ($customers as $customer) {
    // There is no SQL execution
    $orders = $customer->orders;
}
Copy the code

Reduced from 101 queries to 2.

Make your code “clean”

By simplicity, I don’t mean the amount of code, but the meaning. Take the following code for example

1 / / way
if($num > 100) {return 1
}else{
    return 2
}

2 / / way
return $num > 100 ? 1 : 2;
Copy the code

We all like the second option when the logic is simple, but if the logic is more complex, I prefer option 1. Although it may be many lines, the idea is concise, so that you can understand it and he can understand it.

Why bother writing an expression that makes you feel awesome!!

Add a try to the view’s PHP code

When writing actions or model methods, we usually use try…. to ensure code stability Catch syntax, but rarely used in the view of yii2, remember, use it too! Take this code for example.

/ / view
<?= \app\components\WechatLangSideMenu::widget();? >
Copy the code

What if the above code fails? I recommend writing it as follows


      
try {
    echo \app\components\WechatLangSideMenu::widget();
}catch(\Exception $e){
	// You can write your own error handling without handling.
}
? >
Copy the code

Caution is the parent of safety.

Do not write dead, use constant or configuration.

Some code requires some judgment, and the reference to judgment is certain values, such as the code below

if($this->type === 1) {return "Article";
}else if($this->type === 2) {return "Column";
}
Copy the code

I recommend it

if($this->type === Item::ARTICLE_TYPE){
    return "Article";
}else if($this->type === Item::TOPIC_TYPE){
    return "Column";
}
Copy the code

ARTICLE_TYPE and TOPIC_TYPE are constants of the Item model.

Using migration scripts

As I’ve said many times before, and again this time, use migration to manage the database portion of a YIi2 program.

And these scripts should be put together in your version control. Remember, migration scripts usually have two parts.

  • Structure of the script
  • Import of seed data

Many people ignore the second category. In addition, if your table has a prefix when doing the migration script, it will be written as follows in the script

{{%user}}// discuz_user
Copy the code

A matter of time

When using yii2 to develop mysql web applications, we like to use time stamps for the time class fields of the data table. Generally, there will be fields of record generation time and update time in the table.

Please use the built-in TimestampBehavior class of Yii2 for their updates, then we don’t need to worry about filling the field data, as shown in the following code

namespace app\models;

use Yii;
use yii\behaviors\TimestampBehavior;

class Article extends \yii\db\ActiveRecord {
    
    public function behaviors(a){
        return[['class'=> TimestampBehavior::className(), ] ]; }}Copy the code

Therefore, I recommend naming the time field in the data table as follows

  • Generation time created_at
  • Update time updated_AT

The above code is sufficient without specifying fields.

Remember: Remove the required restriction in rules for created_AT and updated_AT fields.

Parent class or behavior

In fact, I do not exclude any kind of, each has its own advantages and disadvantages, the parent class is simple to use but increased coupling, behavior coupling degree is low but configuration is more complex than the direct parent class.

Conceptually, of course, it’s a little different

  • Behavior attributes attached to some classes
  • Parent class Attributes common to classes

My usage (not necessarily right), especially in modules I like to add a parent class to the controller.

To develop the

After the program is developed, there are still some configurations for yii2 program, many of which you must already know.

Entrance to the file

First, we need to change the operation mode of YIi2 from development mode to production mode. The general code is as follows

// index.php
defined('YII_DEBUG') or define('YII_DEBUG'.false);
defined('YII_ENV') or define('YII_ENV'.'prod');
Copy the code

An error page

For a stable program, it doesn’t matter if you report an error, what matters is how you handle it after reporting an error. Since users think it is good and helpful to developers, I wrote an article before, you can see “Implementing YouTube Style error handling page with Yii2”.

urlManager

Strictly speaking, this should be done in the development phase. In order to make the search engine better, and to increase the security of the application, we should beautify the URL, such as

/index.php? r=admin/user/index/ / into/admin/user - index. HTML
Copy the code

For details about urlManager configuration and common Web server configuration, you can see the quick check table I wrote before, there are ready-made codes.

summary

Accidentally write so much, of course yiI2 development should pay attention to more than these, later slowly say.