查看 路由文章 如果您更喜欢改用 PHP 来定义 API 路由。
当使用 Vue.js 或 React 等客户端框架时,将需要调用服务端 API。这些 API 可以使用你的主题来定义,其中每个页面代表一个 API 端点。
页面代表一个转换层,它位于您的 CMS 组件和返回到您应用程序的 JSON 响应之间。大多数对象,例如模型和集合,都支持 JSON 序列化,并且可以直接作为响应返回。
以最简单的形式,API 资源可以通过返回一个 Twig 变量来构成,使用 response() Twig 函数。此函数会覆盖页面内容,并向浏览器返回一个自定义响应。
url = "/api/foobar"{% do response({ foo: 'bar' }) %}上述调用将返回一个内容类型为 application/json 的响应。
{ "foo": "bar" }在大多数情况下,你将把组件变量转换为响应。
{% do response({
id: post.id,
title: post.title,
email: post.author.email,
created_at: post.created_at,
updated_at: post.updated_at
}) %}collect()Twig 函数 为响应构建一个集合。这个 push 方法用于将项目推送到集合中,并且可以用于自定义每个结果。
{% set result = collect() %}
{% for post in posts %}
{% do result.push({
id: post.id,
title: post.title,
email: post.author.email,
created_at: post.created_at,
updated_at: post.updated_at
}) %}
{% endfor %}
{% do response(result) %}所有 Twig 条件都可以在标记中使用,以影响响应,并且最后一次响应调用将被发送到浏览器。
使用 this.request.method Twig 属性 来检查请求方法。
{% if this.request.method == 'GET' %}
<!-- Do GET Logic -->
{% else %}
<!-- Method Unsupported -->
{% endif %}这 abort() Twig 函数 可用于中止请求并返回 404 响应。
{% if post %}
{% do response(post) %}
{% else %}
{% do abort(404) %}
{% endif %}由于 API 在页面或布局的标记部分中定义,所有组件和生命周期事件都可用。
中间件允许你将通用逻辑应用于多个端点,例如检查认证或节流请求。 一个CMS 布局(带有优先级模式)可用于将逻辑应用于多个页面,并且布局逻辑在页面逻辑之前执行。
请务必包含 {% page %} Twig 标签,以便包含页面逻辑。例如,名为 api.htm 的布局可以包含任何条件逻辑。
description = "API Authentication"
is_priority = 1{% if someCondition %}
{% page %}
{% else %}
{% do response({ message: 'Condition not met' }, 400) %}
{% endif %}所有使用该布局的页面都将应用该布局的条件。
layout = "api"{% do response({ success: true }) %}始终使用布局中的优先模式以确保布局内容首先运行。
:::
在某些情况下,您可能希望调用某个组件的或页面内部的 AJAX 处理程序。 这可以通过使用 ajaxHandler() Twig 函数 实现。
url = "/api/signin
[account]{% set result = ajaxHandler('onSignin') %}
{% if result.error %}
{% do response({ message: 'Login Failed' }, 401) %}
{% else %}
{% do response({ success: true }) %}
{% endif %}您还可以调用一个处理器,并将其直接作为响应传递。该响应包括页面上设置的变量以及函数返回的数组值。
{% do response(ajaxHandler('onSubmitPost')) %}它还将自动处理重定向。请参阅Twig 函数文章以了解更多详情。
在使用模型和集合时,建议将数据包裹在 data 属性中返回。将响应包裹起来可以提供一致的接口。
返回模型资源。
url = "/api/blog/post/:slug"
[section post]
handle = "Blog\Post"
identifier = "slug"{% if post %}
{% do response({
data: post
}) %}
{% else %}
{% do abort(404) %}
{% endif %}返回一个集合资源。
url = "/api/blog/posts"
[collection posts]
handle = "Blog\Post"{% do response({
data: posts
}) %}当使用分页集合进行响应时,建议使用 pager() Twig 函数 来构建响应,使用 links 和 meta 属性。
{% set posts = blog.paginate(3) %}
{% set pager = pager(posts) %}
{% do response({
data: posts,
links: pager.links,
meta: pager.meta
}) %}上述将输出以下 JSON 格式。
{
"data": {},
"links": {
"first": "https://yoursite.tld/api/blog/posts?page=1",
"last": "https://yoursite.tld/api/blog/posts?page=1",
"prev": null,
"next": null
},
"meta": {
"path": "https://yoursite.tld/api/blog/posts",
"per_page": 3,
"total": 2,
"current_page": 1,
"last_page": 1,
"from": 1,
"to": 2
}
}这些是一些代码片段如何使用的实用示例。
以下示例将 users 变量设置为 User 插件 中找到的所有用户。avatar 关系在之后被预加载,然后如果找到了头像,avatar_thumb 属性将为每个用户设置为一个缩略图 URL。
## pages/api/users.htm
url = "/api/users"function onStart()
{
$this['users'] = \RainLab\User\Models\User::all();
}{# Load up the avatar relation #}
{% do users.load('avatar') %}
{# Set the 'avatar_thumb' attribute on each user #}
{% for user in users %}
{% do user.setAttribute(
'avatar_thumb',
user.avatar.getThumbUrl(100, 100, {mode: 'crop'})|default(null)
) %}
{% endfor %}
{# Respond with the user #}
{% do response({
data: users
}) %}