为API创建代码生成器的能力,以便免于不断创建相同的控制器,模型,路由器,中间件,迁移,框架,过滤器,验证等的需求,从而节省了下一代。 手动(即使在熟悉且方便的框架中),对我来说似乎很有趣。
我研究了OpenAPI规范的典型性和精妙之处,我喜欢它的线性和能够描述1-3级深度的任何实体的结构和类型的能力。 从那时起,我就已经熟悉Laravel(Yii2以前曾使用它,CI,但它们不那么受欢迎)以及json-api数据输出格式-整个体系结构与连接图一起落在了我的脑海。

让我们继续示例。
假设我们在OAS中描述了以下实体:
ArticleAttributes: description: Article attributes description type: object properties: title: required: true type: string minLength: 16 maxLength: 256 facets: index: idx_title: index description: required: true type: string minLength: 32 maxLength: 1024 facets: spell_check: true spell_language: en url: required: false type: string minLength: 16 maxLength: 255 facets: index: idx_url: unique show_in_top: description: Show at the top of main page required: false type: boolean status: description: The state of an article enum: ["draft", "published", "postponed", "archived"] facets: state_machine: initial: ['draft'] draft: ['published'] published: ['archived', 'postponed'] postponed: ['published', 'archived'] archived: [] topic_id: description: ManyToOne Topic relationship required: true type: integer minimum: 1 maximum: 6 facets: index: idx_fk_topic_id: foreign references: id on: topic onDelete: cascade onUpdate: cascade rate: type: number minimum: 3 maximum: 9 format: double date_posted: type: date-only time_to_live: type: time-only deleted_at: type: datetime
如果我们运行命令
php artisan api:generate oas/openapi.yaml --migrations
然后我们得到以下生成的对象:
1)实体控制器
<?php namespace Modules\V1\Http\Controllers; class ArticleController extends DefaultController { }
他已经知道GET / POST / PATCH / DELETE,为此他将通过模型进入表格,还将为其生成迁移。 DefaultController始终可供开发人员使用,因此可以为所有控制器实现功能。
2)文章实体模型
<?php namespace Modules\V2\Entities; use Illuminate\Database\Eloquent\SoftDeletes; use rjapi\extension\BaseModel; class Article extends BaseModel { use SoftDeletes;
如您所见,注释出现在这里// >>>道具>>>和// >>>方法>>>-需要用它们才能将代码空间与用户代码空间分开。 还有一个标签/主题关系-belognsToMany / belongsTo,它们分别将Article实体与标签/主题联系起来,提供了通过单个GET请求在关系json-api中访问它们或通过更新文章来更改它们的机会。
3)实体迁移,并具有回滚支持(反射/原子性):
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateArticleTable extends Migration { public function up() { Schema::create('article', function(Blueprint $table) { $table->bigIncrements('id'); $table->string('title', 256); $table->index('title', 'idx_title'); $table->string('description', 1024); $table->string('url', 255); $table->unique('url', 'idx_url');
迁移生成器支持所有类型的索引(包括组合索引)。
4)滚动请求的路由器:
不仅为基本查询创建了路由,还为与其他实体的关系创建了路由,这些查询将通过1个查询和扩展作为批量操作进行拉取,以便能够批量创建/更新/删除数据。
5)FormRequest用于预处理/验证请求:
<?php namespace Modules\V1\Http\Requests; use rjapi\extension\BaseFormRequest; class ArticleFormRequest extends BaseFormRequest {
这里的一切都很简单-生成用于验证属性和关系的规则,以将主实体与Relations方法中的实体链接起来。
最后,最好的部分是查询示例:
http:
显示文章,按关系固定所有标签,在第2页上进行分页,限制为10,然后按年龄排序。
如果我们不需要显示文章的所有字段:
http:
按多个字段排序:
http:
过滤(或属于WHERE子句的任何内容):
http:
创建实体的示例(在本例中为文章):
POST http://laravel.loc/v1/article { "data": { "type":"article", "attributes": { "title":"Foo bar Foo bar Foo bar Foo bar", "description":"description description description description description", "fake_attr": "attr", "url":"title title bla bla bla", "show_in_top":1 } } }
答案是:
{ "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar", "description": "description description description description description", "url": "title title bla bla bla", "show_in_top": 1 }, "links": { "self": "laravel.loc/article/1" } } }
看到链接->自我中的链接? 你可以立即
GET http://laravel.loc/article/1
或保存以供将来参考。
GET http://laravel.loc/v1/article?include=tag&filter=[["updated_at", ">", "2017-01-03 12:13:13"], ["updated_at", "<", "2019-01-03 12:13:15"]] { "data": [ { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 1", "description": "The quick brovn fox jumped ower the lazy dogg", "url": "http://example.com/articles_feed 1", "show_in_top": 0, "status": "draft", "topic_id": 1, "rate": 5, "date_posted": "2018-02-12", "time_to_live": "10:11:12" }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "1" } ] } } } ], "included": [ { "type": "tag", "id": "1", "attributes": { "title": "Tag 1" }, "links": { "self": "laravel.loc/tag/1" } } ] }
他返回了一个对象列表,其中每个对象的类型,其ID,整个属性集,然后是其自身的链接,通过
include =标记在url中请求的关系
,根据规范,包括关系没有任何限制,例如
include =标记,主题,城市及其所有内容都将包含在
关系块中,而它们的对象将存储在
include中 。
如果我们想获得1条文章及其所有关系/关系:
GET http://laravel.loc/v1/article/1?include=tag&data=["title", "description"] { "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 123456", "description": "description description description description description 123456", }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "3" }, { "type": "tag", "id": "1" }, { "type": "tag", "id": "2" } ] } } }, "included": [ { "type": "tag", "id": "3", "attributes": { "title": "Tag 4" }, "links": { "self": "laravel.loc/tag/3" } }, { "type": "tag", "id": "1", "attributes": { "title": "Tag 2" }, "links": { "self": "laravel.loc/tag/1" } }, { "type": "tag", "id": "2", "attributes": { "title": "Tag 3" }, "links": { "self": "laravel.loc/tag/2" } } ] }
这是一个向现有实体添加关系的示例-一个请求:
PATCH http://laravel.loc/v1/article/1/relationships/tag { "data": { "type":"article", "id":"1", "relationships": { "tag": { "data": [{ "type": "tag", "id": "2" },{ "type": "tag", "id": "3" }] } } } }
答案是:
{ "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 1", "description": "The quick brovn fox jumped ower the lazy dogg", "url": "http://example.com/articles_feed 1", "show_in_top": 0, "status": "draft", "topic_id": 1, "rate": 5, "date_posted": "2018-02-12", "time_to_live": "10:11:12" }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "2" }, { "type": "tag", "id": "3" } ] } } }, "included": [ { "type": "tag", "id": "2", "attributes": { "title": "Tag 2" }, "links": { "self": "laravel.loc/tag/2" } }, { "type": "tag", "id": "3", "attributes": { "title": "Tag 3" }, "links": { "self": "laravel.loc/tag/3" } } ] }
您可以将其他选项转移到控制台生成器:
php artisan api:generate oas/openapi.yaml --migrations --regenerate --merge=last
因此,您告诉生成器-创建带有迁移的代码(您已经看到了)并重新生成代码,以保存的历史记录中的最新更改存储它,而不会影响代码的自定义部分,而只影响那些自动生成的部分(即,并在代码中用特殊注释突出显示特殊块)。 可以指定后退步骤,例如:--
merge = 9 (将生成后退9步),代码生成日期为过去
--merge =“ 2017-07-29 11:35:32” 。
该库的一位用户建议为查询生成功能测试-通过添加
--tests选项,您可以运行测试以确保您的API正常运行而不会出错。
此外,您可以使用许多选项(它们均通过配置器灵活配置,配置器位于生成的模块中,例如:
/Modules/V2/Config/config.php ):
<?php return [ 'name' => 'V2', 'query_params'=> [
自然,如有必要,所有配置都可以点开/关。 有关代码生成器其他功能的更多信息,请参见下面的链接。 始终欢迎捐款。
感谢您的关注,并取得了成功。
文章资源: