Yii2启动Restful风格Api接口,用于前后端分离项目或者对外的第三方Api接口

发布时间 2023-05-22 11:33:17作者: 浪里小韭菜

使用高级Yii2模板:yii2-app-advanced

原因:建立Restful的Api相当于一个独立的项目,如backend(后端)、frontend(前端),又因为Api与后端项目相识度高,只是封装方法对外暴露,因此需要复制一份backend,重命名为api项目,放在根目录,与backend、frontend、common等同级。

一、准备工作

1、下载安装集成工具,如 wampServer、phpStudy 等,集成了php 、apache、mysql等环境,本人用的是wampServer ,7.xphp,

 2、mysql的访问地址:http://localhost/phpmyadmin/,账号:root,密码是空,不用填

 3、如果使用wampServer默认的访问目录www,则项目下载到该目录;

  3.1、如果自定义项目的位置,则需要设置apache的httpd-hosts.conf文件,位置: D:\wamp64\bin\apache\apache2.4.37\conf\extra,添加配置

<VirtualHost *:80>
   ServerName api.appadvanced.dev
    DocumentRoot "E:/my_advanced/api/web/"
   <Directory "E:/my_advanced/api/web/">
	   # use mod_rewrite for pretty URL support
	   RewriteEngine on
	   # If a directory or a file exists, use the request directly
	   RewriteCond %{REQUEST_FILENAME} !-f
	   RewriteCond %{REQUEST_FILENAME} !-d
	   # Otherwise forward the request to index.php
	   RewriteRule . index.php

	   # use index.php as index file
	   DirectoryIndex index.php
	   AllowOverride All
	   Require local
   </Directory>
</VirtualHost>

<VirtualHost *:80>
   ServerName appadvancedbackend.dev
	ServerAlias *.appadvancedbackend.dev
   DocumentRoot "E:/my_advanced/backend/web"
   <Directory "E:/my_advanced/backend/web">
	   # use mod_rewrite for pretty URL support
	   RewriteEngine on
	   # If a directory or a file exists, use the request directly
	   RewriteCond %{REQUEST_FILENAME} !-f
	   RewriteCond %{REQUEST_FILENAME} !-d
	   # Otherwise forward the request to index.php
	   RewriteRule . index.php

	   DirectoryIndex index.php
	   AllowOverride All
	   Require local

   </Directory>
</VirtualHost>

 3.2、需要设置系统的hosts文件, 位置:C:\Windows\System32\drivers\etc\hosts,如果看不见,那是隐藏了,打开文件夹选择查看,勾选隐藏的项目

127.0.0.1 api.appadvanced.dev
127.0.0.1 appadvancedfrontend.dev

 3.3、至此,设置了 api 项目的访问地址: api.appadvanced.dev , 和 后台 backend 的访问地址: appadvancedbackend.dev

二、安装Yii2.0

通过 Composer 安装

1、这是安装Yii2.0的首选方法。如果你还没有安装 Composer,你可以进入这里下载Composer-Setup.exe进行安装。

2、安装完 Composer,进行验证是否安装成功,在cmd中输入 composer

composer

如果出现如图,即表示安装成功

3、运行下面的命令来安装 Composer Asset 插件:

composer global require "fxp/composer-asset-plugin:^1.2.0"
// 或
php composer.phar global require "fxp/composer-asset-plugin:^1.2.0"

4、安装高级的应用程序模板,运行下面的命令:

composer create-project yiisoft/yii2-app-advanced my_advanced
// 或
php composer.phar create-project yiisoft/yii2-app-advanced my_advanced

5、初始化高级模板,初始化即可安装依赖,依赖文件在vender中

cd my_advanced
init

注:因为依赖需要访问国外,所以安装经常失败,多尝试安装

// 进入根目录,安装指令
composer update
// 或
composer install

 6、如果能正常访问即可

// 后端访问目录,自定义的配置直接指定到了web目录,默认访问index.php
http://appadvancedbackend?r=site/index

// 这个链接是默认安装到wampServer的www目录中的
http://localhost/basic/web/index.php?r=site/index

7、修改数据库连接

打开 common\config\main-local.php,本地配置数据库连接信息

'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=127.0.0.1;dbname=yii2advanced',
            'username' => 'root',
            'password' => 'root',
            'charset' => 'utf8',
        ],

8、根目录执行 migrate数据库迁移,生成user数据表

yii migrate

9、拷贝backend目录,命名为api

打开api\config\main.php 修改id,controllerNamespace

return [
    'id' => 'app-api',
    'basePath' => dirname(__DIR__),
    'controllerNamespace' => 'api\controllers',
]

10、打开common\config\bootstrap.php添加以下别名

Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api');

11、在准备工作中已经配置好 Api 的项目的路径,可直接访问

// Api访问目录,自定义的配置直接指定到了web目录,默认访问index.php
http://api.appadvanced.dev?r=site/index

 

三、为什么要单独创建API应用

单独创建API应用,目的是便于维护,可以避免以下问题

  • 配置的冲突
  • 控制器的命名不便
  • url美化规则冲突
  • 分工明确frontend为前台目录;backend为后台目录;api为api目录

1、打开 api\controllers 新建一个User控制器,继承 yii\rest\ActiveController,命名为 UserController,代码如下:

<?php
namespace api\controllers;
use yii\rest\ActiveController;

class UserController extend extends ActiveController
{
    public $modelClass = 'common\models\User';
    
}

这里创建 user控制器继承 yii\rest\ActiveController 并指定要操作的模型

2、启用JSON 输入

配置 request 应用程序组件的 parsers 属性使用 yii\web\JsonParser 用于 JSON 输入

打开配置文件 api\config\main-local.php 修改为如下代码:

<?php

$config = [
    'components' => [
        'request' => [
            ...
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',

            ],
            ...
        ],
    ],
];
...

3、配置URL规则

为刚才的 user控制器添加url美化规则,打开 api\config\main.php 修改 components属性,添加下列代码:

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

...

ok,到此就成了一个 符合 RESTful 风格的API
看起来在控制器了什么也没有写,只是指定了一个模型,但是她的背后完成了很多的功能哦,列表如下:

  • GET /users: 逐页列出所有用户
  • HEAD /users: 显示用户列表的概要信息
  • POST /users: 创建一个新用户
  • GET /users/123: 返回用户 123 的详细信息
  • HEAD /users/123: 显示用户 123 的概述信息
  • PATCH /users/123: and PUT /users/123: 更新用户123
  • DELETE /users/123: 删除用户123
  • OPTIONS /users: 显示关于末端 /users 支持的动词
  • OPTIONS /users/123: 显示有关末端 /users/123 支持的动词

 

四、如何访问呢

1、在cmd中,你可以使用 curl命令进行访问,命令如下:

curl -i -H "Accept:application/json" "http://api.appadvanced.dev/users"

命令行下还是比较麻烦的,也不方便测试,推荐使用 postman、apifox等测试工具,也可以使用网页版的接口测试工具

2、你可能发现了 访问任何路由地址都是加的s,users , 为什么呢? 资源,你要理解 资源二字,既然是资源肯定是个集合,肯定有一大堆,所以要加上复数,我是这么理解的。

你说我就是不想加上s,我就想采用http://api.appadvanced.dev/user 这种方式来进行访问,好吧,可以,满足你,只是不推荐

继续打开配置文件api\config\main.php修改刚才添加的 urlManager 如下:

'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        ['class' => 'yii\rest\UrlRule', 
        'controller' => 'user',
        'pluralize' => false,    //设置为false 就可以去掉复数形式了
        ],
    ],
]

加入 'pluralize' => false, 就表示去掉复数形式了,再次强调不推荐

ok,在控制器中我们没有写任何一句代码,他就给我们生成许多方法,但是有时候我们可能需要修改一些代码,来达到我们想要的效果,比如连表查询,然后再返回数据

3、接下来我们就实现这样的功能:

打开刚才新建的user控制器, 重写 action方法:

<?php

namespace api\controllers;
use yii\rest\ActiveController;

class UserController extend extends ActiveController
{
    public $modelClass = 'common\models\User';
    
    public function actions()
    {
        $action= parent::actions(); // TODO: Change the autogenerated stub,隐藏ActiveController原有的方法,以便重写方法
        unset($action['index']);
        unset($action['create']);
        unset($action['update']);
        unset($action['delete']);
    }
    
    public function actionIndex()
    {
        //你的代码
    }
    
}

这样我们就可以重写他的代码了。哈哈

4、我们再新建一个自己的 action

<?php

namespace api\controllers;
use yii\rest\ActiveController;

class UserController extend extends ActiveController
{
    public $modelClass = 'common\models\User';
    
    public function actions()
    {
        $action= parent::actions(); // TODO: Change the autogenerated stub
        unset($action['index']);
        unset($action['create']);
        unset($action['update']);
        unset($action['delete']);
    }
    
    public function actionIndex()
    {
        //你的代码
    }
    
    public function actionSendEmail()  //假如是get请求
    {
        //业务逻辑
    }
    
}

 

5、修改 api\config\main.php

'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        [
            'class' => 'yii\rest\UrlRule', 
            'controller' => 'user',
            //'pluralize' => false,    //设置为false 就可以去掉复数形式了
            'extraPatterns'=>[   // 配置对应的url  /send-email,如果是想搜索,这里可以配置 GET search
                'GET send-email'=>'send-email'
            ],
        ],
    ],
]

然后试着访问一下 http://api.appadvanced.dev/users/send-email

ps:你自己编写的任何 action 都要在 extraPatterns 进行配置

6、自定义响应返回的格式,

  如果有非200的报错throw,但是前端想要正确的响应格式,code依旧200,只是会将错误code和msg都响应出去,这时候就需要修改 config

  修改 api\config\main.php 在 components 添加如下代码:

'response' => [
            'class' => 'yii\web\Response',
            'on beforeSend' => function ($event) {
                $response = $event->sender;
                $response->data = [
                    'success' => $response->isSuccessful,
                    'code' => $response->getStatusCode(),
                    'message' => $response->statusText,
                    'data' => $response->data,
                ];
                $response->statusCode = 200;
            },
        ],

这里统一使用 200来表示,当然并不是所有的都是  200 ,,如 code = 0