跳转到主要内容
dustise 提交于 17 October 2014

Drupal 8的目标之一就是开箱即用,Drupal核心现在有了一套ReST API

这使得用户在使用Drupal 8的各种功能输入内容之后,不仅可以把内容呈现到标准的Drupal前端中,而且还可以输出给移动应用以及其他的能使用JSON数据的应用之中。

ReST

Drupal 8使用两个Module来提供ReST API。rest模块,为Angular JS之类的能够使用’Accept: application/json’头提供最简单的响应。他的工作很简单,只是Drupal 8 Entity的序列化输出。

下面是一个JSON响应的例子

{
    "nid": [{
        "value": "1"
    }],
    "uuid": [{
        "value": "c0de5b48-d165-4970-8e05-5fccc692845f"
    }],
    "type": [{
        "target_id": "article"
    }],
    "langcode": [{
        "value": "und"
    }],
    "title": [{
        "value": "Rusticus Vulpes"
    }],
    "uid": [{
        "target_id": "0"
    }],
    "status": [{
        "value": "1"
    }],
    "body": [{
        "value": "This is the body of this node",
        "format": "plain_text",
        "summary": "And this is the summary"
    }],
    "comment": [{
        "status": "2",
        "cid": "5",
        "last_comment_timestamp": "1411546941",
        "last_comment_name": "",
        "last_comment_uid": "1",
        "comment_count": "5"
    }],
    "field_image": [{
        "target_id": "28",
        "display": null,
        "description": null,
        "alt": "Facilisi gemino nisl probo veniam.",
        "title": "",
        "width": "399",
        "height": "308"
    }],
    "field_tags": [{
        "target_id": "4"
    }]
}

HAL

启用了hal模块,可以配置使用这一模块处理”Accept: application/hal+json”头。HAL的响应在普通的JSON响应内容之外,还加入了_links_embedded两个键,用于包含关联信息和请求实体。

下面是一个hal+json的响应

{
    "_links": {
        "self": {
            "href": "http:\/\/d8.dev\/node\/1"
        },
        "type": {
            "href": "http:\/\/d8.dev\/rest\/type\/node\/article"
        },
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/uid": [{
            "href": "http:\/\/d8.dev\/user\/0",
            "lang": "und"
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/revision_uid": [{
            "href": "http:\/\/d8.dev\/user\/0"
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/field_image": [{
            "href": "http:\/\/d8.dev\/sites\/default\/files\/field\/image\/generateImage_Af38aP.jpg",
            "lang": "und"
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/field_tags": [{
            "href": "http:\/\/d8.dev\/taxonomy\/term\/4",
            "lang": "und"
        }]
    },
    "uuid": [{
        "value": "c0de5b48-d165-4970-8e05-5fccc692845f"
    }],
    "type": [{
        "target_id": "article"
    }],
    "langcode": [{
        "value": "und"
    }],
    "title": [{
        "value": "Rusticus Vulpes",
        "lang": "und"
    }],
    "_embedded": {
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/uid": [{
            "_links": {
                "self": {
                    "href": "http:\/\/d8.dev\/user\/0"
                },
                "type": {
                    "href": "http:\/\/d8.dev\/rest\/type\/user\/user"
                }
            },
            "uuid": [{
                "value": "aa69dd40-a5ad-4346-8d07-7c01f3e9e726"
            }],
            "lang": "und"
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/revision_uid": [{
            "_links": {
                "self": {
                    "href": "http:\/\/d8.dev\/user\/0"
                },
                "type": {
                    "href": "http:\/\/d8.dev\/rest\/type\/user\/user"
                }
            },
            "uuid": [{
                "value": "aa69dd40-a5ad-4346-8d07-7c01f3e9e726"
            }]
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/field_image": [{
            "_links": {
                "self": {
                    "href": "http:\/\/d8.dev\/sites\/default\/files\/field\/image\/generateImage_Af38aP.jpg"
                },
                "type": {
                    "href": "http:\/\/d8.dev\/rest\/type\/file\/file"
                }
            },
            "uuid": [{
                "value": "84c9914b-d5e1-4235-b911-17e0381948bd"
            }],
            "uri": [{
                "value": "http:\/\/d8.dev\/sites\/default\/files\/field\/image\/generateImage_Af38aP.jpg"
            }],
            "lang": "und"
        }],
        "http:\/\/d8.dev\/rest\/relation\/node\/article\/field_tags": [{
            "_links": {
                "self": {
                    "href": "http:\/\/d8.dev\/taxonomy\/term\/4"
                },
                "type": {
                    "href": "http:\/\/d8.dev\/rest\/type\/taxonomy_term\/tags"
                }
            },
            "uuid": [{
                "value": "069bc39f-a41a-4fc6-a404-4df9e92e7b0b"
            }],
            "lang": "und"
        }]
    },
    "status": [{
        "value": "1",
        "lang": "und"
    }],
    "body": [{
        "value": "This is the body of this node",
        "format": "plain_text",
        "summary": "And this is the summary",
        "lang": "und"
    }],
    "comment": [{
        "status": "2",
        "cid": "5",
        "last_comment_timestamp": "1411546941",
        "last_comment_name": "",
        "last_comment_uid": "1",
        "comment_count": "5",
        "lang": "und"
    }]
}

HAL响应和JSON相应的不同之处在于,HAL把JSON中用ID表达的相关数据例如图片、用户以及TAG等,替换成为_link元素,其中包含类型、URI以及文档链接。

如何实践?

大多数DEMO需要这一ISSUE中的补丁。

要实践这些功能的最简单方法是使用drupal-rest-test工具来配置一个Drupal 8的ReST开发环境。该工具利用Drush安装一个Drupal,启用相关模块并进行配置和授权。这个项目的文档中包含了相关环境的信息。

补充说明

从HAL或者JSON中获取数据很简单,其响应内容具有基本的自我描述能力。真正的问题在于通过API对Node进行添加或者修改。多数此类文档都是来源于针对代码的反向工程。有个补丁可以使用application/json格式向Drupal提交新的Node。这是drupal-rest-test项目中post-rest.php的实现;同一项目中,post-hal.php中实现了application/hal+json格式的同样过程。

使用application/json提交node的例子

POST /entity/node
Content-type: application/json

{
    "title": [
        "test"
    ],
    "type": [
        {
            "value": "article"
        }
    ]
}

利用application/hal+json提交node的例子:

POST /entity/node Content-type: application/hal+json

{
    "title": [
        "test"
    ],
    "type": [
        {
            "value": "article"
        }
    ],
    "_links": {
        "type": {
            "href": "http:\/\/d8.dev\/rest\/type\/node\/article"
        }
    }
}

创建带有关系的Entity

创建同其他Entity具有关系的Entity很重要。例如留言Entity和Node Enity的关系。

使用application/json创建comment的例子(感谢@bertramakers)。

POST /entity/comment
Content-type: application/json

{
    "entity_type": "node",
    "field_name": "comment",
    "entity_id": [
        {
            "target_id": 1
        }
    ],
    "comment_body": [
        {
            "value": "Example comment message."
        }
    ]
}

使用application/hal+json完成同样内容

POST /entity/comment
Content-type: application/hal+json

{
    "entity_type": [
        "node"
    ],
    "field_name": [
        "comment"
    ],
    "comment_body": [
        "test"
    ],
    "_links": {
        "http:\/\/d8.dev\/rest\/relation\/comment\/comment\/entity_id": [
            {
                "href": "http:\/\/d8.dev\/node\/1"
            }
        ],
        "type": {
            "href": "http:\/\/d8.dev\/rest\/type\/comment\/comment"
        }
    },
    "_embedded": {
        "http:\/\/d8.dev\/rest\/relation\/comment\/comment\/entity_id": [
            {
                "uuid": "af3710e7-fec3-4064-b500-b30d838236f5"
            }
        ]
    }
}

这就是使用HAL创建comment的最少数据。

使用Drupal和ReST搭建前端

我们创建了drupal-8-rest-angular项目来从可用度角度来对这一API进行测试。这个项目尝试使用AngularJS应用的方式来重新实现Bartik主题。这个项目使用Drupal 8中的自定义Views来从API以application/json格式获取需要的信息。

这个项目演示了包含API endpoint中缺失的创建完整Drupal前端的各种功能。目前尚无方法可以获取站点名称等Drupal基础站点信息。可以获取Block的信息,而获取一个Article的内容并展现给用户,平均需要5次json请求。

如果想要使用ReST,请关注meta issue报告问题

Drupal 版本