店滴开发者手册店滴开发者手册
首页
指南
插件
接口
智能设备
element后台
SDK
首页
指南
插件
接口
智能设备
element后台
SDK
  • 插件

    • 插件开发指南
    • 后台接口
    • 插件API开发指南
    • 后端
    • 目录结构
    • 配置
    • 接口文档
    • 插件模型开发指南
    • 插件搜索功能开发指南
    • 命令行

插件API开发指南

1. API目录结构

插件的API相关文件通常放在插件目录下,按照功能模块进行组织。

1.1 目录结构示例

addons/
└─diandi_mall/
    ├─api/                # API控制器目录
    │  ├─GoodsController.php   # 商品API控制器
    │  ├─OrderController.php   # 订单API控制器
    │  └─SearchController.php  # 搜索API控制器
    ├─config/             # 配置目录
    │  └─api.php           # API路由配置
    ├─api.php             # API入口文件
    └─models/             # 模型目录
        ├─goods/          # 商品模型
        └─order/          # 订单模型

2. API入口文件

2.1 入口文件配置

API入口文件用于注册插件的API路由和配置。

<?php
/**
 * API入口文件
 */
return [
    'modules' => [
        'diandi_mall' => [
            'class' => 'addons\diandi_mall\Module',
        ],
    ],
];

3. API路由配置

3.1 路由配置文件 (config/api.php)

API路由配置文件用于定义插件的API路由规则。

<?php
/**
 * API路由配置
 */
return [
    'goods' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/goods'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
            'GET view' => 'view',
            'POST create' => 'create',
            'PUT update' => 'update',
            'DELETE delete' => 'delete',
        ],
    ],
    'order' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/order'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
            'GET view' => 'view',
            'POST create' => 'create',
            'PUT update' => 'update',
            'DELETE delete' => 'delete',
        ],
    ],
    'search' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/search'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET goods' => 'goods',
            'GET advanced' => 'advanced',
        ],
    ],
];

3.2 路由配置说明

配置项描述必需
class路由规则类,通常使用 yii\rest\UrlRule是
controller控制器映射,格式为 ['插件标识/控制器名称']是
pluralize是否支持复数形式,建议设置为 false是
extraPatterns额外的路由规则,定义HTTP方法和控制器方法的映射是

4. API控制器开发

4.1 基础控制器

API控制器需要继承系统提供的基础API控制器类,以获得统一的功能和特性。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    // API方法
}

4.2 控制器示例

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use addons\diandi_mall\models\goods\Goods;
use addons\diandi_mall\models\goods\GoodsSearch;
use Yii;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品列表
     * @return array
     */
    public function actionList()
    {
        $searchModel = new GoodsSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->success([
            'list' => $dataProvider->getModels(),
            'total' => $dataProvider->getTotalCount(),
            'page' => Yii::$app->request->get('page', 1),
            'pageSize' => $dataProvider->pagination->pageSize,
        ]);
    }

    /**
     * 获取商品详情
     * @return array
     */
    public function actionView()
    {
        $id = Yii::$app->request->get('id');
        $goods = Goods::findOne($id);

        if (!$goods) {
            return $this->error('商品不存在');
        }

        return $this->success($goods);
    }

    /**
     * 创建商品
     * @return array
     */
    public function actionCreate()
    {
        $goods = new Goods();
        $goods->load(Yii::$app->request->post(), '');

        if ($goods->save()) {
            return $this->success($goods);
        } else {
            return $this->error('创建失败', $goods->getErrors());
        }
    }

    /**
     * 更新商品
     * @return array
     */
    public function actionUpdate()
    {
        $id = Yii::$app->request->post('id');
        $goods = Goods::findOne($id);

        if (!$goods) {
            return $this->error('商品不存在');
        }

        $goods->load(Yii::$app->request->post(), '');

        if ($goods->save()) {
            return $this->success($goods);
        } else {
            return $this->error('更新失败', $goods->getErrors());
        }
    }

    /**
     * 删除商品
     * @return array
     */
    public function actionDelete()
    {
        $id = Yii::$app->request->post('id');
        $goods = Goods::findOne($id);

        if (!$goods) {
            return $this->error('商品不存在');
        }

        if ($goods->delete()) {
            return $this->success('删除成功');
        } else {
            return $this->error('删除失败');
        }
    }
}

5. API响应格式

5.1 成功响应

// 成功响应
return $this->success([
    'id' => 1,
    'name' => '商品名称',
    'price' => 99.99,
]);

// 响应格式
{
    "code": 200,
    "message": "操作成功",
    "data": {
        "id": 1,
        "name": "商品名称",
        "price": 99.99
    }
}

5.2 错误响应

// 错误响应
return $this->error('操作失败');

// 带错误信息的错误响应
return $this->error('验证失败', $model->getErrors());

// 响应格式
{
    "code": 400,
    "message": "操作失败",
    "data": null
}

// 带错误信息的响应格式
{
    "code": 400,
    "message": "验证失败",
    "data": {
        "name": ["商品名称不能为空"],
        "price": ["商品价格必须大于0"]
    }
}

6. API参数验证

6.1 请求参数验证

使用Yii2的验证机制对API请求参数进行验证。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use Yii;
use yii\base\Model;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 创建商品
     * @return array
     */
    public function actionCreate()
    {
        $model = new class extends Model {
            public $name;
            public $price;
            public $stock;

            public function rules()
            {
                return [
                    [['name', 'price', 'stock'], 'required'],
                    [['price'], 'number', 'min' => 0],
                    [['stock'], 'integer', 'min' => 0],
                    [['name'], 'string', 'max' => 255],
                ];
            }
        };

        if ($model->load(Yii::$app->request->post(), '') && $model->validate()) {
            // 参数验证通过,创建商品
            $goods = new Goods();
            $goods->name = $model->name;
            $goods->price = $model->price;
            $goods->stock = $model->stock;

            if ($goods->save()) {
                return $this->success($goods);
            } else {
                return $this->error('创建失败', $goods->getErrors());
            }
        } else {
            return $this->error('参数验证失败', $model->getErrors());
        }
    }
}

7. API权限控制

7.1 权限检查

在API控制器中添加权限检查,确保只有授权用户能够访问API。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use Yii;

/**
 * 订单API控制器
 */
class OrderController extends ApiController
{
    /**
     * 获取订单列表
     * @return array
     */
    public function actionList()
    {
        // 检查用户是否登录
        if (!Yii::$app->user->isGuest) {
            $userId = Yii::$app->user->id;
            // 查询用户的订单
            // ...
        } else {
            return $this->error('请先登录');
        }
    }
}

8. API性能优化

8.1 缓存使用

使用缓存减少数据库查询,提高API响应速度。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use addons\diandi_mall\models\goods\Goods;
use Yii;
use yii\caching\FileCache;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品详情
     * @return array
     */
    public function actionView()
    {
        $id = Yii::$app->request->get('id');
        $cacheKey = 'goods_' . $id;

        $cache = new FileCache();
        $goods = $cache->get($cacheKey);

        if ($goods === false) {
            $goods = Goods::findOne($id);
            if ($goods) {
                // 缓存商品详情,有效期1小时
                $cache->set($cacheKey, $goods, 3600);
            }
        }

        if (!$goods) {
            return $this->error('商品不存在');
        }

        return $this->success($goods);
    }
}

8.2 查询优化

优化数据库查询,减少不必要的字段和关联查询。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use addons\diandi_mall\models\goods\Goods;
use Yii;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品列表
     * @return array
     */
    public function actionList()
    {
        $query = Goods::find()
            ->select(['id', 'name', 'price', 'stock', 'status', 'created_at'])
            ->where(['status' => 1])
            ->orderBy(['created_at' => SORT_DESC]);

        $pagination = new \yii\data\Pagination([
            'totalCount' => $query->count(),
            'pageSize' => Yii::$app->request->get('pageSize', 10),
            'page' => Yii::$app->request->get('page', 0),
        ]);

        $list = $query
            ->offset($pagination->offset)
            ->limit($pagination->limit)
            ->all();

        return $this->success([
            'list' => $list,
            'total' => $pagination->totalCount,
            'page' => $pagination->page + 1,
            'pageSize' => $pagination->pageSize,
        ]);
    }
}

9. API调试

9.1 调试工具

使用Postman、Insomnia等API调试工具测试API接口。

9.2 日志记录

在API控制器中添加日志记录,便于调试和排查问题。

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use Yii;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品列表
     * @return array
     */
    public function actionList()
    {
        // 记录请求参数
        Yii::info('Goods list request: ' . json_encode(Yii::$app->request->queryParams), 'api');

        // 业务逻辑
        // ...

        // 记录响应结果
        Yii::info('Goods list response: success', 'api');

        return $this->success($data);
    }
}

10. API版本控制

10.1 版本控制策略

使用URL路径或请求头进行API版本控制。

10.1.1 URL路径版本控制

<?php
/**
 * API路由配置
 */
return [
    'v1/goods' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/v1-goods'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
        ],
    ],
    'v2/goods' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/v2-goods'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
        ],
    ],
];

10.1.2 请求头版本控制

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use Yii;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品列表
     * @return array
     */
    public function actionList()
    {
        // 获取版本号
        $version = Yii::$app->request->headers->get('X-API-Version', 'v1');

        switch ($version) {
            case 'v1':
                // v1版本逻辑
                break;
            case 'v2':
                // v2版本逻辑
                break;
            default:
                return $this->error('不支持的API版本');
        }

        // 业务逻辑
        // ...
    }
}

11. 常见问题

11.1 API路由404

可能原因:

  • 路由配置错误
  • 控制器不存在
  • 控制器方法不存在
  • 插件未安装

解决方案:

  • 检查路由配置是否正确
  • 确认控制器文件存在
  • 确认控制器方法存在
  • 确认插件已正确安装

11.2 API响应500

可能原因:

  • 代码语法错误
  • 数据库查询错误
  • 权限不足
  • 依赖服务不可用

解决方案:

  • 检查代码语法是否正确
  • 检查数据库连接和查询
  • 确认用户权限是否足够
  • 检查依赖服务是否可用

11.3 API参数验证失败

可能原因:

  • 请求参数格式错误
  • 必填参数缺失
  • 参数类型错误
  • 参数值超出范围

解决方案:

  • 检查请求参数格式是否正确
  • 确保所有必填参数都已提供
  • 确保参数类型正确
  • 确保参数值在有效范围内

12. 最佳实践

12.1 API设计建议

  1. RESTful设计:遵循RESTful API设计规范
  2. 版本控制:实现API版本控制,确保向后兼容
  3. 参数验证:对所有API请求参数进行严格验证
  4. 错误处理:统一的错误处理机制,返回清晰的错误信息
  5. 性能优化:使用缓存、查询优化等手段提高API性能
  6. 安全性:注意API安全,防止SQL注入、XSS等攻击
  7. 文档完善:提供详细的API文档,包括参数说明和示例

12.2 API开发建议

  1. 模块化设计:将API功能拆分为多个模块,便于维护和扩展
  2. 代码复用:提取公共代码,减少重复代码
  3. 测试覆盖:为API编写单元测试,确保API功能正确
  4. 日志记录:完善的日志记录,便于调试和问题排查
  5. 监控告警:实现API监控和告警,及时发现和解决问题

13. 示例代码

13.1 完整API控制器示例

<?php
namespace addons\diandi_mall\api;

use common\controllers\addons\ApiController;
use addons\diandi_mall\models\goods\Goods;
use addons\diandi_mall\models\goods\GoodsSearch;
use Yii;
use yii\caching\FileCache;

/**
 * 商品API控制器
 */
class GoodsController extends ApiController
{
    /**
     * 获取商品列表
     * @return array
     */
    public function actionList()
    {
        $searchModel = new GoodsSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->success([
            'list' => $dataProvider->getModels(),
            'total' => $dataProvider->getTotalCount(),
            'page' => Yii::$app->request->get('page', 1),
            'pageSize' => $dataProvider->pagination->pageSize,
        ]);
    }

    /**
     * 获取商品详情
     * @return array
     */
    public function actionView()
    {
        $id = Yii::$app->request->get('id');
        $cacheKey = 'goods_' . $id;

        $cache = new FileCache();
        $goods = $cache->get($cacheKey);

        if ($goods === false) {
            $goods = Goods::findOne($id);
            if ($goods) {
                // 缓存商品详情,有效期1小时
                $cache->set($cacheKey, $goods, 3600);
            }
        }

        if (!$goods) {
            return $this->error('商品不存在');
        }

        return $this->success($goods);
    }

    /**
     * 创建商品
     * @return array
     */
    public function actionCreate()
    {
        $goods = new Goods();
        $goods->load(Yii::$app->request->post(), '');

        if ($goods->save()) {
            // 清除相关缓存
            $cache = new FileCache();
            $cache->delete('goods_list');

            return $this->success($goods);
        } else {
            return $this->error('创建失败', $goods->getErrors());
        }
    }

    /**
     * 更新商品
     * @return array
     */
    public function actionUpdate()
    {
        $id = Yii::$app->request->post('id');
        $goods = Goods::findOne($id);

        if (!$goods) {
            return $this->error('商品不存在');
        }

        $goods->load(Yii::$app->request->post(), '');

        if ($goods->save()) {
            // 清除相关缓存
            $cache = new FileCache();
            $cache->delete('goods_' . $id);
            $cache->delete('goods_list');

            return $this->success($goods);
        } else {
            return $this->error('更新失败', $goods->getErrors());
        }
    }

    /**
     * 删除商品
     * @return array
     */
    public function actionDelete()
    {
        $id = Yii::$app->request->post('id');
        $goods = Goods::findOne($id);

        if (!$goods) {
            return $this->error('商品不存在');
        }

        if ($goods->delete()) {
            // 清除相关缓存
            $cache = new FileCache();
            $cache->delete('goods_' . $id);
            $cache->delete('goods_list');

            return $this->success('删除成功');
        } else {
            return $this->error('删除失败');
        }
    }
}

13.2 API路由配置示例

<?php
/**
 * API路由配置
 */
return [
    'goods' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/goods'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
            'GET view' => 'view',
            'POST create' => 'create',
            'PUT update' => 'update',
            'DELETE delete' => 'delete',
        ],
    ],
    'order' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/order'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET list' => 'list',
            'GET view' => 'view',
            'POST create' => 'create',
            'PUT update' => 'update',
            'DELETE delete' => 'delete',
        ],
    ],
    'search' => [
        'class' => 'yii\rest\UrlRule',
        'controller' => ['diandi_mall/search'],
        'pluralize' => false,
        'extraPatterns' => [
            'GET goods' => 'goods',
            'GET advanced' => 'advanced',
        ],
    ],
];
Prev
后台接口
Next
后端