cebe/yii2-openapi

此包已被废弃,不再维护。作者建议使用 php-openapi/yii2-openapi 包。

从 OpenAPI 3 规范生成完整的 REST API 应用程序。

2.0-beta2 2023-01-05 13:21 UTC

README

此仓库已迁移至 https://github.com/php-openapi/yii2-openapi
请使用新的包 php-openapi/yii2-openapi

REST API 应用程序生成器,基于 Yii2 和 openapi 3.0 YAML -> Yii2。

基于 Gii,Yii 框架代码生成器

Latest Stable Version Latest Alpha Version Total Downloads License yii2-openapi

简单来说,这是什么?

一个基于 OpenAPI 和 Yii 框架的 PHP API 应用的代码生成器。

输入:OpenAPI 3.0 YAML 或 JSON(通过 cebe/php-openapi

输出:带有控制器、模型和数据库模式的 Yii 框架应用程序

功能

目前可用的功能

  • 生成路径映射、控制器API 端点 的动作。CRUD 端点是即用型,其他端点是生成为需要实现的具体函数
  • 根据 OpenAPI 架构生成 模型 和验证
  • 从 OpenAPI 架构生成 数据库架构
  • 为架构更改生成 数据库迁移
  • 通过 Faker 提供 假数据 以供开发使用

要求

  • PHP 7.1 或更高版本(与 PHP 8 一起正常工作)

安装

composer require php-openapi/yii2-openapi:^2.0@beta

使用方法

您可以在现有的应用程序中使用此包或使用 yii2-app-api 应用程序模板开始一个新项目。有关模板的用法,请参阅模板仓库的说明。

在您的现有 Yii 应用程序配置(适用于控制台和网页)

<?php
$config = [
    // ... this is your application config ...
];

if (YII_ENV_DEV) {
    // enable Gii module
    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = [
        'class' => \yii\gii\Module::class,
        'generators' => [
            // add ApiGenerator to Gii module
            'api' => \cebe\yii2openapi\generator\ApiGenerator::class,

            // --------- OR ---------
            // to disable generation of migrations files or with default config change
            'api' => [
              'class' => \cebe\yii2openapi\generator\ApiGenerator::class,
              'generateMigrations' => false, # this config can also be applied in CLI command
            ],
        ],
    ];
}

return $config;

要使用网页生成器,请打开 index.php?r=gii 并选择 REST API 生成器

在控制台中,您可以运行生成器 ./yii gii/api --openApiPath=@app/openapi.yaml。其中 @app/openapi.yaml 应该是您的 OpenAPI 规范文件的绝对路径。这可以是 JSON,也可以是 YAML(有关支持的格式,请参阅 cebe/php-openapi)。

运行 ./yii gii/api --help 查看所有选项。示例:禁用迁移文件生成 ./yii gii/api --generateMigrations=0

有关示例 OpenAPI 规范,请参阅 Petstore 示例

OpenAPI 扩展

此库理解以下 OpenAPI 规范的扩展

x-faker

您可以为属性指定用于生成假数据的自定义 PHP 代码

    Post:
      properties:
        id:
          type: integer
        tags:
          type: array
          items:
            type: string
          example: ['one', 'two']
          x-faker: "$faker->randomElements(['one', 'two', 'three', 'four'])"

要避免为特定的模型属性生成 faker 代码,请使用值 false

    Post:
      properties:
        age:
          type: integer
          x-faker: false

allOf 中使用

    Invoice:
      type: object
      required:
        - id
      properties:
        id:
          type: integer

    Order:
      type: object
      required:
        - id
      properties:
        id:
          type: integer
        invoice:
          allOf:
            - $ref: '#/components/schemas/Invoice'
            - x-faker: false

x-table

为存储在数据库中的模型定义的架构指定表名。您可以通过设置 x-table: false 生成不基于 \yii\base\Model 的非数据库模型,无需迁移

x-pk

显式指定与 "id" 不同的表的主键名称

    Post:
      x-table: posts
      x-pk: uid
      properties:
        uid:
           type: integer
        title:
           type: string

x-db-type

明确指定列的数据库类型。(必须仅包含真实的数据库类型!(例如 jsonjsonbuuidvarchar 等。))。如果将 x-db-type 设置为 false,属性将被处理为虚拟的;它将被添加到模型中作为公共属性,但在迁移生成时将被跳过。

x-db-type 的示例值包括

  • false(布尔值假)
  • 作为字符串,其值可以是
    • 文本
    • 文本[]
    • INTEGER PRIMARY KEY AUTO_INCREMENT
    • decimal(12,4)
    • json
    • varchar
    • VARCHAR
    • SMALLINT UNSIGNED ZEROFILL
    • MEDIUMINT(10) UNSIGNED ZEROFILL COMMENT "comment"(注意这里的双引号)

不允许这样的值

  • int null default null after low_price(null 和 default 将分别由 nullabledefault 键处理)
  • MEDIUMINT(10) UNSIGNED ZEROFILL NULL DEFAULT '7' COMMENT 'comment' AFTER seti,ADD INDEX t (w

如果同时提供了 enumx-db-type,则对于数据库列模式(迁移),只考虑 x-db-type,忽略 enum

x-indexes

指定表索引

    Post:
      x-table: posts
      x-indexes:
          - 'visible,publish_date'
          - 'unique:title' #for unique attributes also unique validation check will be added
          - 'gist:metadata' #for postgres will generate index using GIST index type
      properties:
        id:
           type: integer
           x-db-type: INTEGER PRIMARY KEY AUTO_INCREMENT
        title:
           type: string
        visible:
            type: boolean
        publish_date:
            type: string
            format: date
        metadata:
           type: object
           x-db-type: JSON
           default: '{}' 

x-db-default-expression

可以通过数据库表达式提供默认值的能力

created_at:
  readOnly: true
  type: string
  format: datetime
  x-db-type: datetime
  nullable: false
  x-db-default-expression: current_timestamp()

注意:如果同时存在 defaultx-db-default-expression,则考虑 default

created_at:
  readOnly: true
  type: string
  format: datetime
  x-db-type: datetime
  nullable: false
  x-db-default-expression: current_timestamp() # this will be ignored
  default: "2011-11-11" # this will be considered

另请参阅:https://dev.mysqlserver.cn/doc/refman/8.0/en/data-type-defaults.html

x-fk-on-delete

允许在迁移中设置数据库表中行的 ON DELETE 事件的外键约束。例如

  components:
    schemas:
      User:
        type: object
        description: x on-x (update|delete) foreign key constraint
        properties:
          id:
            type: integer
          name:
            type: string
      Post:
        type: object
        description: x on-x (update|delete) foreign key constraint
        properties:
          id:
            type: integer
          title:
            type: string
          user:
            allOf:
              - $ref: '#/components/schemas/User'
              - x-fk-on-update: CASCADE
          user_2:
            allOf:
              - $ref: '#/components/schemas/User'
              - x-fk-on-update: CASCADE
              - x-fk-on-delete: SET NULL
          user_3:
            allOf:
              - $ref: '#/components/schemas/User'
              - x-fk-on-delete: SET NULL
          user_4:
            $ref: '#/components/schemas/User' # without any constraints

x-fk-on-update

允许在迁移中设置数据库表中行的 ON UPDATE 事件的外键约束。例如,参见上面的 x-fk-on-delete 部分。

x-fk-column-name

在关系列的情况下提供自定义数据库表列名。这不会反映在模型关系、faker 等。

  components:
    schemas:
      Webhook:
        type: object
        description: example for x-fk-column-name
        properties:
          id:
            type: integer
          name:
            type: string
          user:
            $ref: '../openapi.yaml#/components/schemas/User' # this will automatically create `user_id` column
          redelivery_of:
            allOf:
              - $ref: '../openapi.yaml#/components/schemas/Delivery'
              # this will automatically create `redelivery_of_id` column, but to avoid that use below extension
              - x-fk-column-name: redelivery_of # this will create `redelivery_of` column instead of `redelivery_of_id`

多对多关系定义

定义多对多关系有两种方式

没有中间模型的简单多对多

  • 多对多关系的属性名称应与下划线分隔的复数化相关架构名称相等

  • 引用架构应包含对当前架构的镜像引用

  • 可以自动生成连接表的迁移 - 表名应为 [复数化、小写架构名称1]2[复数化、小写架构名称2],按字母顺序排列;例如,对于架构 Post 和 Tag - 表应为 posts2tags,对于架构 Post 和 Attachement - 表应为 attachments2posts

Post:
  properties:
  ...
    tags:
      type: array
      items:
        $ref: '#/components/schemas/Tag'

Tag:
  properties:
  ...
    posts:
      type: array
      items:
        $ref: '#/components/schemas/Post'

带有中间模型的多对多

这种方式允许在两个模型之间创建多个多对多关系

  • 定义具有所有必要属性的中间模型。只有一个重要要求 - 中间模型名称必须以前缀 'junction_' 开头(这个前缀将仅用于内部,并在表和模型生成之前被移除)
# Model TeamMembers with table team_members will be generated with columns team_id, user_id and role
junction_TeamMembers:
   team:
      $ref: '#/components/schemas/Team'
   user:
      $ref: '#/components/schemas/User'
   role:
     type: string
  • 两个多对多相关架构都必须具有引用 "junction_*" 架构的属性。这些属性将用作关系名称
Team:
  properties:
  ...
     team_members:
       type: array
       items:
         $ref: '#/components/schemas/junction_TeamMembers'

User:
  properties:
  ...
    memberships: #You absolutely free with naming for relationship attributes
      type: array
      items:
        $ref: '#/components/schemas/junction_TeamMembers'

处理 NOT NULL 约束

DB 迁移中的 NOT NULL 由 OpenAPI 架构的 nullablerequired 属性确定。例如,属性 = 'my_property'。

  • 如果您没有定义属性 "required" 或通过 "nullable",则它默认为 NULL
  ExampleSchema:
    properties:
      my_property:
        type: string
  • 如果您在 "required" 中定义了属性,则它为 NOT NULL
  ExampleSchema:
    required:
     - my_property
    properties:
      my_property:
        type: string
  • 如果您通过 "nullable" 定义了属性,则它覆盖 "required",例如,在这种情况下允许 NULL
  ExampleSchema:
    required:
      - my_property
    properties:
      my_property:
        type: string
        nullable: true
  • 如果您通过 "nullable" 定义了属性,则它覆盖 "required",例如,在这种情况下为 NOT NULL
  test_table:
    required:
    properties:
      my_property:
        type: string
        nullable: false

处理 enum(枚举)

它在所有 3 个数据库中工作:MySQL、MariaDb 和 PgSQL。

 test_table:
   properties:
     my_property:
       enum:
         - one
         - two
         - three

注意:枚举值的变化并不简单。对于Mysql和MariaDb,将生成迁移,但在许多情况下还需要对其进行自定义修改。对于Pgsql迁移,枚举值的变化将不会生成,需要手动处理。

如果提供了 x-db-type,则将忽略数据库列模式(迁移)。

numeric 的处理(#numeric,#MariaDb)

精度默认值 = 10,比例默认值 = 2

  • 您可以定义类似于 "numeric(precision,scale)" 的属性
 test_table:
   properties:
     my_property:
       x-db-type: decimal(12,4)

数据库结果 = decimal(12,4)

  • 您可以定义类似于 "numeric(precision)" 的属性,默认比例默认值 = 2
 test_table:
   properties:
     my_property:
       x-db-type: decimal(12)

数据库结果 = decimal(12,2)

  • 您可以定义类似于 "numeric" 的属性,精度默认值 = 10 和比例默认值 = 2
 test_table:
   properties:
     my_property:
       x-db-type: decimal

数据库结果 = decimal(10,2)

timestamp 数据库列数据类型的处理

如果字段定义为

created_at:
    type: string
    format: date-time # or datetime
    example: '2020-03-14T21:42:17Z'
    readOnly: true

则选择的数据库类型将是 timestamp。这是设计决定的。如果需要 datetime 数据类型,请使用 x-db-type 如下

created_at:
    type: string
    format: date-time # or datetime
    example: '2020-03-14T21:42:17Z'
    x-db-type: datetime
    readOnly: true

假设

从OpenAPI描述生成代码时,有许多可能的方法可以实现合适的结果。因此,目前有一些假设和限制被应用于使此功能正常工作。以下是一个(可能不完整)的列表

  • 当前实现最适合遵循 JSON:API 指引的OpenAPI描述。
    • 当前请求和响应格式/模式不是从OpenAPI模式中提取的,如果不遵循JSON:API,则可能需要手动调整。
  • 名称为 id 的列/字段/属性被视为该库的主键,并由DB/Yii自动处理;因此,请从验证 rules() 中删除它
    • 其他字段目前可以用于主键,使用 x-pk OpenAPI扩展(见下文),但这可能在所有情况下都不会正确工作,如果发现任何问题,请报告错误。

其他需要注意的事项

向现有表添加列

当在API模型中添加新字段时,将生成新迁移以将这些字段添加到表中。对于已经投入生产的项目,应考虑调整生成的迁移以添加现有数据记录的默认值。

一个重要的例子是添加具有 NOT NULL 约束的新列,它不提供默认值。此类迁移将在表不为空时失败

$this->addColumn('{{%company}}', 'name', $this->string(128)->notNull());

在PostgreSQL数据库中失败

向表 {{%company}} 添加列名称 string(128) NOT NULL ...异常:SQLSTATE[23502]:非空违规:7 错误:列 "name" 包含空值

解决方案是创建列,允许NULL,将值设置为默认值,然后稍后添加空约束。

$this->addColumn('{{%company}}', 'name', $this->string(128)->null());
$this->update('{{%company}}', ['name' => 'No name']);
$this->alterColumn('{{%company}}', 'name', $this->string(128)->notNull());

屏幕截图

Gii 生成器表单

Gii Generator Form

生成的文件

Gii Generated Files

开发

要贡献或尝试,请参阅在本地设置此项目的步骤,见 CONTRIBUTING.md

支持

需要帮助您的API项目?

提供专业支持、咨询以及软件开发服务

https://www.cebe.cc/en/contact

此库的开发由 cebe.:cloud: "您的专业部署平台" 赞助。