我试图将MT的API转换为GraphQL(正在进行中)
這是2019年可移動式類型(Movable Type)的聖誕日曆第三天的文章。
順便說一下,我正在12月9日星期一寫下這篇文章。 真相是,我已經完全忘記了註冊和註冊日期,並且收到了反饋後匆忙寫這篇文章。非常抱歉自己註冊後忘記了。。。
我尝试将MT的API转换为GraphQL(进行中)。
大家知道GraphQL吗?它在2015年左右发布,被Facebook等大公司开发作为替代RestAPI的方法,并被GitHub、Airbnb、Netflix等大公司采用,成为了讨论的话题。顺便一提,我的了解只限于它是个方便的东西,所以我一直想尝试一下,这次借着AdventCalendar的机会,我把MT的API转化成了GraphQL并学习了一下。
然而,’途中’這個詞的意思是GraphQL本身的理解還不夠深入,而且覆蓋MT的所有API需要極長的時間,所以目前只處於入門階段。
我們將繼續進行開發,希望您能以溫和的態度看待這次的導入部分。
(歡迎提出建議和指正)
GraphQL是什么?
把GraphQL简单解释一下:它是一种API。
除了MT的API之外,至今为止多数都是使用被称为REST(RESTful)的方式实现的。
休息 (xiū xí)
-
- リソース(取得できる結果)ごとにURLがある
-
- URLによって得られる結果が決まっている
- 情報の操作(取得、作成、更新、削除)は全てHTTPメソッド(GET、POST、PUT、DELETE)
如果使用MT的Data API来获取内容数据,格式如下:
MT ContentData API 参考文档
[获取] http://example.com/mt/mt-data-api.cgi/v4/sites/{site_id}/contentTypes/{content_type_id}/data
那么,得到的结果将以以下形式呈现。(引用自参考资料)
{
"totalResults": 1,
"items": [
{
"author": {
"displayName": "Hello, world!",
"id": 1,
"userpicUrl": "Hello, world!"
},
"basename": "Hello, world!",
"blog": {
"id": 1
},
"createdDate": "Hello, world!",
"data": [
{
"data": "Hello, world!",
"id": 1,
"label": "Hello, world!",
"type": "Hello, world!"
}
],
"date": "Hello, world!",
"id": 1,
"label": "Hello, world!",
"modifiedBy": {
"displayName": "Hello, world!",
"id": 1,
"userpicUrl": "Hello, world!"
},
"modifiedDate": "Hello, world!",
"status": "Hello, world!",
"unpublishedDate": "Hello, world!",
"updatable": true
}
]
}
如果您未从管理画面更新,访问上述URL将返回相同的结果。
每个资源都有一个URL作为其特征,因此只能通过上述URL获取ContentData的信息。
如果想获取网站名称或内容类型名称等信息,则需要再通过另一个URL获取。
当使用API动态获取信息并在屏幕上显示时,
如果屏幕只需要ContentData的信息就足够,那就没有问题。
然而通常情况下,我们需要了解是哪个网站的内容数据,以及是哪种类型的内容数据,因此需要更多的信息。在这种情况下,使用RestAPI需要进行多次访问。
-
- 获取网站信息(/sites/{site_id})
-
- 获取内容类型信息(/sites/{site_id}/contentTypes/{content_type_id})
- 获取内容数据(/sites/{site_id}/contentTypes/{content_type_id}/data/{content_data_id})
使用者一方也需要思考在哪个终点会返回什么结果才能使用,而开发者需要根据想要获取的结果变化而不断增加终点。
另外,对于破坏性变更(例如获取结果发生变化)的终端点,则会将版本号从/v4/更改为/v5等,同时保证以前的终端点仍可获取结果,这也是一个特点之一。
如果场景在某种情况下发生了一个字段的增加或减少,我们会更新版本号。
由于这些原因,终端点数量不断增加,每次都需要重新制作手册,需要进行发布,这变得非常繁琐。
GraphQL是一种用于API开发的查询语言。
GraphQL在解决上述REST的问题时,具有以下特点:
-
- URL(エンドポイント)は一つ
-
- 取得したいデータをアクセス時にbodyに送る(POST送信)
- 情報の操作(取得、作成、更新、削除)はbodyないで書く(Query、Mutation)
为了学习GraphQL,我将MT的API的一部分转化为了GraphQL。
我尽力以简单易懂的方式实现了它(尽管我的知识有限)。
[帖子] http://example.com/mt/plugins/GraphQL/graphql.cgi
身体
{
sites {
name
}
contentdata(Filter: {siteID: 1}) {
id
label
}
}
得到的JSON结果如下所示。
{
"data": {
"contentdata": [
{
"id": "48",
"label": "Now burning pamphlets at this very."
},
{
"id": "49",
"label": "That they were awake was the."
},
{
"id": "50",
"label": "Now hanging a fair faces trod!"
}
],
"sites": [
{
"name": "test"
},
{
"name": "test1"
}
]
}
}
在结果部分,数据中包含了”contentdata”和”sites”。
“contentdata”是指内容数据的信息,”sites”是指网站的信息,
可以在一个请求中获取到内容数据和网站的信息。
我接下来将尝试获取网站的所有页面和其中包含的内容数据。
[POST] http://example.com/mt/plugins/GraphQL/graphql.cgi
[发送] http://example.com/mt/plugins/GraphQL/graphql.cgi
身体
{
sites {
name
contentdata {
label
}
}
}
得到的JSON结果如下所示
{
"data": {
"sites": [
{
"contentdata": [
{
"label": "Now burning pamphlets at this very."
},
{
"label": "That they were awake was the."
},
{
"label": "Now hanging a fair faces trod!"
}
],
"name": "test"
},
{
"contentdata": [
{
"label": "test"
},
{
"label": "test"
}
],
"name": "test1"
}
]
}
}
有了这个JSON,可以显示每个网站的内容数据列表等。
你可能注意到了,实际上在返回的结果中,第一个样本的内容数据包含id和label,
而第二个样本只返回label。
特征的第二个部分是在访问时将想要获取的数据发送到请求的body中。
以下是一个选项的中文释义:
第一个
{
sites {
name
}
contentdata(Filter: {siteID: 1}) {
id
label
}
}
在contentdata中写入了id和label,因此返回的结果中也有id和label。
第二个是
{
sites {
name
contentdata {
label
}
}
}
由于 contentdata 中只写了标签,所以只会返回标签作为结果。
在Rest中,针对每个终端点指定的结果都会返回,所以用户端(前端)需要接收不必要的数据。
* 附注:对于MT,可以通过在内容数据列表获取API中添加字段来筛选所需的字段,但除非有这样的便利实现,否则将返回实施方指定的所有字段。
在GraphQL中,用户可以通过编写所需的字段来接收自己所需的数据。
总结
这次只介绍了GraphQL的浅显部分,
还有很多特点和方便之处,
但因为我的学习不足,无法达到能够向他人解释的程度,就到这里为止。
我想写一些关于我制作插件时使用的模块以及我遇到的困难,但是我自己还没有归纳整理好,所以希望将来有机会再写。
如果你以前使用过MT的API,但不知道GraphQL是什么,我希望你能稍微了解一下,嗯,这样的话我会很高兴。