As you all know, I have been modifying the wechat mini program of “A Bei’s Knowledge Sharing” recently, using the restful function in Yii2. Next, I will share some problems and tips I have encountered.

Let’s start with the small program code link

Start sharing.

URL rewriting

We know that restful urls look like this

  • GET /users
  • POST /users
  • DELETE /users/1

Our default URL form for yii2 is index.php? R = the controller/action.

Although Yii2 already provides restful routing rules, we still need the server to support URL rewriting to remove index.php.

I am using Nginx and the configuration is as follows

location / {
    if (!-e $request_filename){
        rewrite ^/(.*) /index.php last;
    }
}
Copy the code

If you have Apache you can do this

// Apache needs to support URL override with its AllowOverride set to all
AllowOverride:all

// Add. Htaccess to the web directory and hide the contents of the index. PHP file as followsRewriteEngine on RewriteCond %{REQUEST_FILENAME} ! -f RewriteCond %{REQUEST_FILENAME} ! -d RewriteRule . index.phpCopy the code

or

RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} ! -f RewriteCond %{REQUEST_FILENAME} ! -d RewriteRule ^(.*)\? *$ index.php/$1 [L,QSA]
Copy the code

Don’t DELETE

By default, yii2 restful already provides five actions — Index, View, Update, Create, and DELETE — to accommodate different behaviors on resources. Maybe you don’t need delete in your interface, there are two methods

Configure URL rules (recommended). For example, IF I do not want to enable DELETE /users/1, you can configure the corresponding URL rules as follows

[
    'class'= >'yii\rest\UrlRule'.'controller'= >'user'.'except'= > ['delete']],Copy the code

We know that these built-in methods are implemented using actions. We can override this function.

class UserController extends ActiveController {
    public $modelClass = 'app\models\User';

    public function actions(a) {
        $actions = parent::actions();
        unset($actions['delete']);
        return$actions; }... }Copy the code

Both methods can be implemented but return different results, so if you are interested, try it out for yourself.

Add an action called ABC

I want to add an actionAbc method to the controller. How do I configure that? If I look at the code below, I’ll do it again in urlManager.

[
    'class'= >'yii\rest\UrlRule'.'controller'= >'user'.'except'= > ['delete'.'update'.'index'].'extraPatterns'= > ['POST abc'= >'abc',]],Copy the code

So you can call the ABC Action of the User controller via POST /users/ ABC.

I need more data

Username =’ user ‘, ‘nickname’ =’ user’, ‘nickname’ =’ user’; username =’ user ‘, ‘nickname’ =’ user’; username =’ user ‘; The order number does not belong to the user table as follows

Add the get parameter we need to add a parameter called expand that is the name of the field you want to fetch, separated by commas.

GET /users? fields='id,nickname'&expand='oTotal'
Copy the code

To configure the User model we need to override a method called extraFields

public function extraFields(a) {
    return [
    	'oTotal'
    ];
}
Copy the code

Next we will write functions that implement oTotal in the User model

public function getOTotal(a){
	return Order::find()->where(['user_id'= >$this->id])->count();
}
Copy the code

What did you find? Did you remember a concept called correlation in YII2, and did you find it easy to get multiple data sets?

Why is json sick

To initiate a server request using a small program, such as creating a new book, we like to write code like this

wx.request({
    method: 'POST'.data: {
        name: name
    },
    url: app.globalData.remoteUrl + '/books'.header: {
        'content-type': 'application/json'
    },
    success: function (res) {}})Copy the code

Here I set ‘content-type’: ‘application/json’. The problem is that I can’t get the name value in json on the server side.

The rest of Yii2 does not support parsing json data in requests by default. Fortunately, this can be done with a small configuration.

// config/web.php
'components'= > ['request'= > ['cookieValidationKey'= >' '.'parsers'= > ['application/json'= >'yii\web\JsonParser',]]]Copy the code

Just add a JsonParser.

Authentication problem

There is login on the web page, but there is no session on the restful page. It doesn’t matter. We can use the Access token to solve the problem. For example, I now require that GET/Users must be logged in.

First configure an access_token field for the User table, and then make a generateAccessToken method under the user model

public function generateAccessToken(a){
    $this->access_token = Yii::$app->security->generateRandomString();
}
Copy the code

This method is mainly used to generate the access_token value.

Yii::$app-> User: yii ::$app-> User: yii ::$app-> User Remember that restful authentication requires the following methods to take effect

public static function findIdentityByAccessToken($token, $type = null)
{
    $model = User::find()->where(['access_token'=>$token])->one();
    return $model;
}
Copy the code

Here the User model is configured, the small remind: if you want to do some of the things the moment login, you can also put findIdentityByAccessToken, such as recording what the login time.

Next, we replicate behaviors for specific interfaces

use yii\filters\auth\HttpBearerAuth;
class UserController extends ActiveController {
    public $modelClass = "app\models\User";

    public function behaviors(a) {

        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator'] ['formats'] = ['application/json'=>Response::FORMAT_JSON];

        $behaviors['authenticator'] = [
            'class'=>HttpBearerAuth::className(),
            'only'= > ['index']];return$behaviors; }}Copy the code

So we’re done. We’re using HttpBearerAuth authentication, which is the Authorization in the header of the request, and yii2 restful supports other things. Remember that the authentication process is automatic, and we can use Yii::$app->user->id in the authentication method to get the id of the current member.

List more parameters

We know that we can GET the member list through GET/Users, but you may say that I want to GET the members from wechat platform (there is a field plat in the user table to represent the source platform), what should I do?

We need to rewrite the interface to accept plAT parameters, and set up a new prepareDataProvider function in the User controller that accepts parameters and generates membership list data, returning an ActiveDataProvider result set.

namespace app\modules\xcx\controllers;

use Yii;
use yii\rest\ActiveController; .class UserController extends ActiveController {
    public $modelClass = 'app\models\User';

    public function actions(a) {
        $actions = parent::actions();
        $actions['index'] ['prepareDataProvider'] = [$this.'prepareDataProvider'];
        return $actions;
    }

    public function prepareDataProvider(a){
        $params = Yii::$app->request->queryParams;

        $modelClass = $this->modelClass;
        $query = $modelClass::find()->where(['plat'=>$params['plat']]);

        $provider = new ActiveDataProvider([
            'query'=>$query->orderBy(['created_at'=>SORT_DESC])
        ]);

        return$provider; }}Copy the code

First of all byThis,’prepareDataProvider’] tells Yii2 that I’m going to customize the method that gets the result set, and I’m going to define this method, The prepareDataProvider can receive the value of the get parameter from Yii::$app-> Request ->queryParams.

summary

The above is so far in the use of yii2 restful development of small programs when the use of some knowledge and skills, I hope to be useful to you, if there is to share ha.