> For the complete documentation index, see [llms.txt](https://espier.gitbook.io/espier/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://espier.gitbook.io/espier/kuang-jia/intro/qing-qiu/controller.md).

# 控制器

控制器都放在 Http 目录，与 [路由](/espier/kuang-jia/intro/qing-qiu/route.md) 相对应，控制器也按照终端进行了分组：

* Admin
* Api
* Frontapi
* Shopapi
* Super
* Thirdparty

每个分组下的目录结构如下：

* Api
  * V1
    * Action   控制器实际所在目录&#x20;
    * Swagger  Swagger定义目录

## 定义控制器

下面是一个基础控制器类的例子。需要注意的是，该控制器继承了 Laravel 的基类控制器。该基类控制器提供了一些便利的方法，比如 middleware 方法，该方法可以为控制器行为添加中间件：

```
namespace AftersalesBundle\Http\Api\V1\Action;

use EspierBundle\Jobs\ExportFileJob;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as Controller;

use AftersalesBundle\Services\AftersalesService;

use Dingo\Api\Exception\ResourceException;

use EspierBundle\Traits\GetExportServiceTraits;

class Aftersales extends Controller
{
    use GetExportServiceTraits;

    public function getAftersalesDetail($aftersales_bn)
    {
        $companyId = app('auth')->user()->get('company_id');
        $aftersalesService = new AftersalesService();
        $result = $aftersalesService->getAftersalesInfo($companyId, $aftersales_bn);

        return $this->response->array($result);
    }
}
```

## 定义 API 文档

在 EcshopX 中每一个控制器方法都是一个 api都是一个接口，接口的出参和入参都是通过 注释来定义的，采用Swagger格式来定义。

控制器分组下的每一个版本都是一组 API ，定义一组 api 需要两步，以 AftersalesBundle 举例如下：

### 1、在 Swagger 目录下定义分组信息

定义 API 基本信息

```php
//AftersalesBundle/Http/Api/V1/Swagger/Info.php
<?php
/**
 * @SWG\Swagger(
 *     schemes={"http"},
 *     host="localhost",
 *     basePath="/api",
 *     @SWG\Info(
 *         version="1.0",
 *         title="售后单商家端调用接口",
 *         description="售后单",
 *     ),
 *     produces={"application/json"},
 * )
 */
```

定义 API Tag

```php
//AftersalesBundle/Http/Api/V1/Swagger/Tags.php
<?php
/**
 * @SWG\Tag(
 *   name="aftersales",
 *   description="售后单",
 * )
 */
```

根据需求定义接口所需数据对象：

```php
//AftersalesBundle/Http/Api/V1/Swagger/AftersalesErrorRespones.php

<?php
namespace AftersalesBundle\Http\Api\V1\Swagger;

/**
 * @SWG\Definition(type="object")
 */
class AftersalesErrorRespones
{
    /**
     * @SWG\Property
     * @var string
     */
    public $message;

    /**
     * @SWG\Property
     * @var string
     */
    public $errors;

    /**
     * @SWG\Property(format="int32")
     * @var int
     */
    public $code;

    /**
     * @SWG\Property(format="int32")
     * @var int
     */
    public $status_code;

    /**
     * @SWG\Property
     * @var string
     */
    public $debug;
}
```

### 2、在 Action 目录中的控制器的方法定义接口

```php
/**
     * @SWG\Get(
     *     path="/aftersales/{$aftersales_bn}",
     *     summary="获取售后单详情",
     *     tags={"aftersales"},
     *     description="获取售后单详情",
     *     operationId="getAftersalesDetail",
     *     @SWG\Parameter(
     *         name="Authorization",
     *         in="header",
     *         description="JWT验证token",
     *         required=true,
     *         type="string",
     *     ),
     *     @SWG\Parameter(
     *         name="aftersales_bn",
     *         in="path",
     *         description="售后单号",
     *         required=true,
     *         type="integer",
     *     ),
     *     @SWG\Response(
     *         response=200,
     *         description="成功返回结构",
     *     ),
     *     @SWG\Response( response="default", description="错误返回结构", @SWG\Schema( type="array", @SWG\Items(ref="#/definitions/AftersalesErrorRespones") ) )
     * )
     */
    public function getAftersalesDetail($aftersales_bn)
    {
        $companyId = app('auth')->user()->get('company_id');
        $aftersalesService = new AftersalesService();
        $result = $aftersalesService->getAftersalesInfo($companyId, $aftersales_bn);

        return $this->response->array($result);
    }
```

Swagger 定义参数详见 [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#dataTypeType)

## 接口文档生成和接口测试

在通过 Swagger 注释的方式定义好接口文档后，可以通过本地开发环境查看和测试接口。

### 一、将 Swagger UI的资源拷贝到public目录中

执行以下命令：

```
php artisan api:swagger --setup
```

### 二、生成指定目录的Swagger API Josn

以 AftersalesBundle 举例如下：

```
php artisan api:swagger --output=src/AftersalesBundle/Http/Api/V1
```

执行完命令后，默认会在 `storage/app/apidocs` 目录下生成类似 `售后单商家端调用接口[1.0].json`文件。

可通过在 `.env` 中新增配置改变存储目录名称

```
SWAGGER_STORAGE_DIR=apidocs
```

### 三、启动服务查看和测试接口

可以通过 PHP 内置 server 快速启动

```
php -S 0.0.0.0:8005 -t public/
```

访问地址为：<http://127.0.0.1:8085/api-doc> 本机开发时，还需要将测试接口的地址修改为本地环境：

```
SWAGGER_API_HOST=127.0.0.1:8080
SWAGGER_API_BASE_PATH=/api
```

使用技巧： 在开发过程中可以，每次修改接口文档都需要重新生成接口文档，可以这样使用命令：

```
php artisan api:swagger --output=src/AftersalesBundle/Http/Api/V1 && php -S 0.0.0.0:8005 -t public/
```
