没有不值得去解决的问题,也没有不值得去学习的技术!

How to Implement RESTful Web Services With the Yii2 Advanced Application Template on Windows 10

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct and only returns data where status is 1

1. Please refer to the previous blog post first: https://www.shuijingwanwq.com/2016/11/26/1436/

2. Prepare to implement a RESTful Web service based on shujujiexi

3. Generate a model using Gii in the frontend application. Edit \environments\dev\frontend\config\main-local.php, as shown in Figure 1

PHP

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = [
        'class' => 'yii\gii\Module',
        'allowedIPs' => ['127.0.0.1', '::1'],
    ];


Generate a model using Gii in the frontend application. Edit \environments\dev\frontend\config\main-local.php
Figure 1

4. Run .\init in Windows PowerShell to overwrite \frontend\config\main-local.php and set the IPs allowed to access Gii, as shown in Figure 2

Run .\init in Windows PowerShell to overwrite \frontend\config\main-local.php and set the IPs allowed to access Gii
Figure 2

5. Open the URL: http://www.kaiqiu_shujujiexi_api.dev/index.php?r=gii. You can now access Gii, as shown in Figure 3

Open the URL: http://www.kaiqiu_shujujiexi_api.dev/index.php?r=gii. You can now access Gii
Figure 3

6. Edit \frontend\config\main.php to enable pretty URLs, as shown in Figure 4

PHP

        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],

Edit \frontend\config\main.php to enable pretty URLs
Figure 4

7. Open the URL: http://www.kaiqiu_shujujiexi_api.dev/gii, as shown in Figure 5

Open the URL: http://www.kaiqiu_shujujiexi_api.dev/gii
Figure 5

8. Create the corresponding model based on the database table kq_schedule, as shown in Figure 6

Create the corresponding model based on the database table kq_schedule
Figure 6

9. Click the Start button under Model Generator to generate the Schedule model with the namespace common\models, so that other applications can use this model later. Internationalization support is not needed at this point, as shown in Figure 7

Click the Start button under Model Generator to generate the Schedule model with the namespace common\models, so that other applications can use this model later. Internationalization support is not needed at this point
Figure 7

10. Click the Generate button to generate the model file \common\models\Schedule.php, as shown in Figure 8

Click the Generate button to generate the model file \common\models\Schedule.php
Figure 8

11. Create a controller \shujujiexi\controllers\ScheduleController.php, as shown in Figure 9

Create a controller \shujujiexi\controllers\ScheduleController.php
Figure 9

 

PHP
<?php
 
namespace shujujiexi\controllers;
 
use yii\rest\ActiveController;
 
class ScheduleController extends ActiveController
{
 
    public $modelClass = 'common\models\Schedule';
}

12. Configure the URL rules by modifying the configuration of the urlManager component, as shown in Figure 10

Configure the URL rules by modifying the configuration of the urlManager component
Figure 10

 

PHP

        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => 'schedule',
                ],
            ],
        ],

13. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct, as shown in Figure 11

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct
Figure 11

14. To implement its own business logic within the shujujiexi application, it is recommended to create a new \shujujiexi\models\Schedule.php that extends \common\models\Schedule, as shown in Figure 12

To implement its own business logic within the shujujiexi application, it is recommended to create a new \shujujiexi\models\Schedule.php that extends \common\models\Schedule
Figure 12

15. Edit the controller \shujujiexi\controllers\ScheduleController.php to re-specify the model as shujujiexi\models\Schedule, as shown in Figure 13

Edit the controller \shujujiexi\controllers\ScheduleController.php to re-specify the model as shujujiexi\models\Schedule
Figure 13

16. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct, as shown in Figure 11

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct
Figure 11

17. In Postman, send a PUT request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1. The response is correct, as shown in Figure 14

In Postman, send a PUT request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1. The response is correct
Figure 14

18. Configure the only and except options to explicitly list which actions are supported and which are disabled. For example, to only support GET list, modify the configuration of the urlManager component, as shown in Figure 15

Configure the only and except options to explicitly list which actions are supported and which are disabled. For example, to only support GET list, modify the configuration of the urlManager component
Figure 15

 

PHP

        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => 'schedule',
                    'only' => ['index'],
                ],
            ],
        ],

19. In Postman, send a PUT request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1. It returns a 404 response, as shown in Figure 16

In Postman, send a PUT request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1. It returns a 404 response
Figure 16

20. Based on the URL rule: ‘GET,HEAD users’ => ‘user/index’, in Postman, send a HEAD request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is empty and can be ignored; all other requests return 404, as shown in Figure 17

Based on the URL rule: 'GET,HEAD users' => 'user/index', in Postman, send a HEAD request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is empty and can be ignored; all other requests return 404
Figure 17

21. To resolve the issue where the 404 response format is HTML, edit \shujujiexi\config\main.php to set the default response format to JSON, as shown in Figure 18

To resolve the issue where the 404 response format is HTML, edit \shujujiexi\config\main.php to set the default response format to JSON
Figure 18

 

PHP

        'response' => [
            'format' => yii\web\Response::FORMAT_JSON,
        ],

22. Execute step 19 again. The 404 response is now in JSON format, as shown in Figure 19

Execute step 19 again. The 404 response is now in JSON format
Figure 19

23. Implement data serialization to include pagination information in the response body to simplify client development. Edit \shujujiexi\controllers\ScheduleController.php, as shown in Figure 20

Implement data serialization to include pagination information in the response body to simplify client development. Edit \shujujiexi\controllers\ScheduleController.php
Figure 20

 

PHP

    public $serializer = [
        'class' => 'yii\rest\Serializer',
        'collectionEnvelope' => 'items',
    ];

24. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct and includes pagination information in the response body, as shown in Figure 21

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. The response is correct and includes pagination information in the response body
Figure 21

25. RESTful APIs are typically stateless. Therefore, configure the user application component by editing \shujujiexi\config\main.php, as shown in Figure 22

RESTful APIs are typically stateless. Therefore, configure the user application component by editing \shujujiexi\config\main.php
Figure 22

 

PHP

        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => false,
            'identityCookie' => ['name' => '_identity-shujujiexi', 'httpOnly' => true],
            'enableSession' => false,
            'loginUrl' => null,
        ],

26. Implement versioning by creating a new directory \shujujiexi\modules. Its structure is shown in Figure 23

Implement versioning by creating a new directory \shujujiexi\modules
Figure 23

27. The contents of \shujujiexi\modules\v1\Module.php are shown in Figure 24

The contents of \shujujiexi\modules\v1\Module.php
Figure 24

28. The contents of \shujujiexi\modules\v1\controllers\ScheduleController.php are shown in Figure 25

The contents of \shujujiexi\modules\v1\controllers\ScheduleController.php
Figure 25

29. The contents of \shujujiexi\modules\v1\models\Schedule.php are shown in Figure 26

The contents of \shujujiexi\modules\v1\models\Schedule.php
Figure 26

30. Configure the URL rules by modifying the configuration of the urlManager component, as shown in Figure 27

Configure the URL rules by modifying the configuration of the urlManager component
Figure 27

31. Configure the module rules, as shown in Figure 28

Configure the module rules
Figure 28

 

PHP

    'modules' => [
        'v1' => [
            'basePath' => '@app/modules/v1',
            'class' => 'shujujiexi\modules\v1\Module'
        ],
    ],

31. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. It returns a 404 response as expected, as shown in Figure 29

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/schedules. It returns a 404 response as expected
Figure 29

32. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct, as shown in Figure 30

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct
Figure 30

33. Adjust the structure of the response data. The default fields are code, message, and data

34. Copy \vendor\yiisoft\yii2\rest\Serializer.php to \shujujiexi\rests\Serializer.php. Its contents extend \yii\rest\Serializer and only retain serializeDataProvider(), as shown in Figure 31

Copy \vendor\yiisoft\yii2\rest\Serializer.php to \shujujiexi\rests\Serializer.php. Its contents extend \yii\rest\Serializer and only retain serializeDataProvider()
Figure 31

 

PHP
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */
 
namespace shujujiexi\rests;
 
use Yii;
 
/**
 * Serializer converts resource objects and collections into array representation.
 *
 * Serializer is mainly used by REST controllers to convert different objects into array representation
 * so that they can be further turned into different formats, such as JSON, XML, by response formatters.
 *
 * The default implementation handles resources as [[Model]] objects and collections as objects
 * implementing [[DataProviderInterface]]. You may override [[serialize()]] to handle more types.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Serializer extends \yii\rest\Serializer
{

    /**
     * Serializes a data provider.
     * @param DataProviderInterface $dataProvider
     * @return array the array representation of the data provider.
     */
    protected function serializeDataProvider($dataProvider)
    {
        if ($this->preserveKeys) {
            $models = $dataProvider->getModels();
        } else {
            $models = array_values($dataProvider->getModels());
        }
        $models = $this->serializeModels($models);

        if (($pagination = $dataProvider->getPagination()) !== false) {
            $this->addPaginationHeaders($pagination);
        }

        if ($this->request->getIsHead()) {
            return null;
        } elseif ($this->collectionEnvelope === null) {
            return $models;
        } else {
            $result = [
                $this->collectionEnvelope => $models,
            ];
            if ($pagination !== false) {
                return ['code' => '00000', 'message' => 'success', 'data' => array_merge($result, $this->serializePagination($pagination))];
                // return array_merge($result, $this->serializePagination($pagination));
            } else {
                return ['code' => '00000', 'message' => 'success', 'data' => $result];
                // return $result;
            }
        }
    }

}


35. Edit the controller \shujujiexi\controllers\ScheduleController.php, as shown in Figure 32

Edit the controller \shujujiexi\controllers\ScheduleController.php
Figure 32

36. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct, as shown in Figure 33

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct
Figure 33

37. To freely define the implementation flow for this request’s response, analyzing \vendor\yiisoft\yii2\rest\ActiveController.php reveals that the default implementation class for the Index action is yii\rest\IndexAction, as shown in Figure 34

To freely define the implementation flow for this request's response, analyzing \vendor\yiisoft\yii2\rest\ActiveController.php reveals that the default implementation class for the Index action is yii\rest\IndexAction
Figure 34

38. Copy \vendor\yiisoft\yii2\rest\IndexAction.php to \shujujiexi\rests\schedule\IndexAction.php, as shown in Figure 35

Copy \vendor\yiisoft\yii2\rest\IndexAction.php to \shujujiexi\rests\schedule\IndexAction.php
Figure 35

39. Edit the controller \shujujiexi\controllers\ScheduleController.php, as shown in Figure 36

Edit the controller \shujujiexi\controllers\ScheduleController.php
Figure 36

 

PHP

    public function actions()
    {
        $actions = parent::actions();
        
        $actions['index']['class'] = 'shujujiexi\rests\schedule\IndexAction';

        return $actions;
    }

40. Edit \shujujiexi\rests\schedule\IndexAction.php, as shown in Figure 37

Edit \shujujiexi\rests\schedule\IndexAction.php
Figure 37

 

PHP
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */
 
namespace shujujiexi\rests\schedule;
 
use Yii;
use yii\rest;
use yii\data\ActiveDataProvider;
 
/**
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class IndexAction extends rest\IndexAction
{
    /**
     * @var callable a PHP callable that will be called to prepare a data provider that
     * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead.
     * The signature of the callable should be:
     *
     * ```php
     * function ($action) {
     *     // $action is the action object currently running
     * }
     * ```
     *
     * The callable should return an instance of [[ActiveDataProvider]].
     */




    /**
     * Prepares the data provider that should return the requested collection of the models.
     * @return ActiveDataProvider
     */
    protected function prepareDataProvider()
    {
        if ($this->prepareDataProvider !== null) {
            return call_user_func($this->prepareDataProvider, $this);
        }

        /* @var $modelClass \yii\db\BaseActiveRecord */
        $modelClass = $this->modelClass;

        return new ActiveDataProvider([
            'query' => $modelClass::find()->where(['status' => 1]),
        ]);
    }
}

41. In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct and only returns data where status is 1, as shown in Figure 38

In Postman, send a GET request to: shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules. The response is correct and only returns data where status is 1
Figure 38

Notes:
1. The model file generated by Gii is stored in the common directory;
2. For v1, it is recommended to implement the methods in the controllers and models within \shujujiexi\controllers and \shujujiexi\models;
3. For v2, if different functionality implementations are needed, it is recommended to override the methods in the controllers and models within \shujujiexi\modules\v1\controllers and \shujujiexi\modules\v1\models;
4. The directory structure of shujujiexi\rests is similar to that of shujujiexi\views, where each controller has its corresponding directory;
5. In each major version (within the corresponding module), use the Accept HTTP request header to determine the minor version number and write conditional code to respond to the respective minor version;
// via parameter
Accept: application/json; version=1.0.0

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系