本地 API
Payload Local API 让你能够在 Node 环境中直接执行与 REST 和 GraphQL 相同的操作,直接在服务器上运行。在这里,你无需处理服务器延迟或网络速度问题,可以直接与数据库交互。
提示:
Local API 在 React Server Components 和其他类似的服务器端上下文中使用时极其强大。使用其他 headless CMS 时,你需要通过 HTTP 层从第三方服务器请求数据,这会显著增加服务器渲染页面的加载时间。而使用 Payload,你无需离开服务器就能获取所需数据。这种方式可以非常快速,绝对是一个改变游戏规则的功能。
以下是使用 Local API 的一些常见场景:
- 在 React Server Components 中获取 Payload 数据
- 通过编写和维护的 Node 种子脚本填充数据
- 开启自定义 Next.js 路由处理器,这些处理器具有额外功能但仍依赖 Payload
- 在访问控制和钩子中使用
访问 Payload
你可以通过两种方式获取当前运行的 payload
对象:
从参数或 req
中访问
在 Payload 内部的大多数地方,你可以直接从钩子、访问控制、验证函数等参数中访问 payload
。这是大多数情况下最简单的访问方式。大多数配置函数都接收 req
(Request) 对象,其中绑定了 Payload (req.payload
)。
示例:
const afterChangeHook: CollectionAfterChangeHook = async ({
req: { payload },
}) => {
const posts = await payload.find({
collection: 'posts',
})
}
导入使用
如果你需要在无法通过函数参数或 req
访问 Payload 的地方使用它,可以手动导入并初始化。
import { getPayload } from 'payload'
import config from '@payload-config'
const payload = await getPayload({ config })
如果你在 Next.js 的开发模式下工作,Payload 会支持热模块替换(HMR)。当你修改 Payload 配置时,Payload 的使用会始终与你的更改保持同步。在生产环境中,getPayload
会自动禁用所有 HMR 功能,因此你无需以不同方式编写代码。我们会为你处理生产模式下的优化。
如果你通过函数参数或 req.payload
访问 Payload,并且在 Next.js 中使用它,HMR 会自动得到支持。
有关在 Next.js 之外使用 Payload 的更多信息,点击此处。
可用的本地选项
由于 Local API 是在仅服务器端上下文中执行的,相比 REST 或 GraphQL,你可以指定更多选项。
Local Option | 描述 |
---|---|
collection | 对 Collection 操作必需。指定要操作的 Collection slug。 |
data | 操作中使用的数据。create 和 update 操作必需。 |
depth | 控制嵌套关系和上传字段的自动填充。 |
locale | 为返回的文档指定语言环境。 |
select | 指定select来控制结果中包含哪些字段。 |
populate | 指定populate来控制从填充文档中包含哪些字段到结果中。 |
fallbackLocale | 为返回的文档指定备用语言环境。 |
overrideAccess | 跳过访问控制。默认情况下,所有 Local API 操作中此属性都设置为 true。 |
overrideLock | 默认情况下忽略文档锁(true )。设置为 false 可强制执行锁定,并在文档被其他用户锁定时阻止操作。更多详情。 |
user | 如果将 overrideAccess 设置为 false ,可以传递一个用户用于访问控制检查。 |
showHiddenFields | 选择接收隐藏字段。默认情况下,根据你的配置,它们会从返回的文档中隐藏。 |
pagination | 设置为 false 可返回所有文档并避免查询文档计数。 |
context | 上下文,将传递给 context 和 req.context ,可被钩子读取。如果你想向钩子传递不应成为文档部分的额外信息时很有用,例如 triggerBeforeChange 选项,BeforeChange 钩子可以读取该选项以确定是否应运行。 |
disableErrors | 设置为 true 时,不会抛出错误。相反,findByID 操作将返回 null ,find 操作将返回空文档数组。 |
disableTransaction | 设置为 true 时,不会初始化数据库事务。 |
下面按操作类型列出了更多可用选项。
事务处理
当你的数据库使用事务时,需要将 req 传递到所有本地操作中。Postgres 使用事务,而 MongoDB 在使用副本集时也会使用事务。即使没有事务,也建议传递 req。
const post = await payload.find({
collection: 'posts',
req, // 建议传递 req
})
注意:
默认情况下,Local API 中所有访问控制检查都是禁用的,但你可以根据需要重新启用它们,并指定特定用户来执行操作。
集合操作
以下集合操作可通过 Local API 使用:
创建#collection-create
// 返回创建的 Post 文档
const post = await payload.create({
collection: 'posts', // 必填
data: {
// 必填
title: 'sure',
description: 'maybe',
},
locale: 'en',
fallbackLocale: false,
user: dummyUserDoc,
overrideAccess: true,
showHiddenFields: false,
// 如果创建支持验证的 auth 文档,
// 可以选择禁用自动发送的邮件
disableVerificationEmail: true,
// 如果你的集合支持上传,可以通过 Local API
// 直接上传文件,需提供完整的绝对文件路径
filePath: path.resolve(__dirname, './path-to-image.jpg'),
// 或者,你可以直接传递 File 对象,
// 如果提供了 file,filePath 将被忽略
file: uploadedFile,
// 如果你想创建另一个文档的副本
duplicateFromID: 'document-id-to-duplicate',
})
查询#collection-find
// 结果将是一个分页的 Posts 集合。
// 更多信息请查看 /docs/queries/pagination。
const result = await payload.find({
collection: 'posts', // 必填
depth: 2,
page: 1,
limit: 10,
pagination: false, // 如果你想禁用分页计数等功能
where: {}, // 在此处传递 `where` 查询条件
sort: '-title',
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
showHiddenFields: true,
})
按 ID 查询#collection-find-by-id
// 结果将是一个 Post 文档。
const result = await payload.findByID({
collection: 'posts', // 必填
id: '507f1f77bcf86cd799439011', // 必填
depth: 2,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
showHiddenFields: true,
})
计数#collection-count
// 结果将是一个包含以下内容的对象:
// {
// totalDocs: 10, // 满足查询条件的文档数量
// }
const result = await payload.count({
collection: 'posts', // 必填
locale: 'en',
where: {}, // 在此处传递 `where` 查询条件
user: dummyUser,
overrideAccess: false,
})
按 ID 更新#collection-update-by-id
// 返回结果将是更新后的 Post 文档
const result = await payload.update({
collection: 'posts', // 必填
id: '507f1f77bcf86cd799439011', // 必填
data: {
// 必填
title: 'sure',
description: 'maybe',
},
depth: 2,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
overrideLock: false, // 默认情况下忽略文档锁定。设置为 false 以强制执行锁定。
showHiddenFields: true,
// 如果你的 collection 支持上传,你可以通过 Local API
// 直接上传文件,只需提供文件的完整绝对路径
filePath: path.resolve(__dirname, './path-to-image.jpg'),
// 如果你正在上传文件并希望替换现有文件
// 而不是生成新的文件名,可以将以下属性设置为 `true`
overwriteExistingFiles: true,
})
批量更新#collection-update-many
// 返回结果将是一个包含以下内容的对象:
// {
// docs: [], // 每个被更新的文档
// errors: [], // 每个错误也包含对应文档的 id
// }
const result = await payload.update({
collection: 'posts', // 必填
where: {
// 必填
fieldName: { equals: 'value' },
},
data: {
// 必填
title: 'sure',
description: 'maybe',
},
depth: 0,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
overrideLock: false, // 默认情况下忽略文档锁定。设置为 false 以强制执行锁定。
showHiddenFields: true,
// 如果你的 collection 支持上传,你可以通过 Local API
// 直接上传文件,只需提供文件的完整绝对路径
filePath: path.resolve(__dirname, './path-to-image.jpg'),
// 如果你正在上传文件并希望替换现有文件
// 而不是生成新的文件名,可以将以下属性设置为 `true`
overwriteExistingFiles: true,
})
删除#collection-delete
// 返回结果将是已删除的 Post 文档
const result = await payload.delete({
collection: 'posts', // 必填
id: '507f1f77bcf86cd799439011', // 必填
depth: 2,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
overrideLock: false, // 默认情况下会忽略文档锁定。设置为 false 以强制执行锁定
showHiddenFields: true,
})
批量删除#collection-delete-many
// 返回结果将是一个包含以下内容的对象:
// {
// docs: [], // 每个被删除的文档
// errors: [], // 发生的任何错误,包括出错文档的 id
// }
const result = await payload.delete({
collection: 'posts', // 必填
where: {
// 必填
fieldName: { equals: 'value' },
},
depth: 0,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
overrideLock: false, // 默认情况下会忽略文档锁定。设置为 false 以强制执行锁定
showHiddenFields: true,
})
认证操作
如果 collection 启用了 Authentication
,将可以使用以下额外的 Local API 操作:
认证
// 如果使用 Next.js,需要从 next/headers 导入 headers,如下所示:
// import { headers as nextHeaders } from 'next/headers'
// 还需要在你的函数或组件中 await headers,如下所示:
// const headers = await nextHeaders()
// 如果在 Next.js 之外使用 Payload,需要相应地提供 headers
// 返回结果格式如下:
// {
// permissions: { ... }, // 包含当前用户权限的对象
// user: { ... }, // 当前登录用户的文档
// responseHeaders: { ... } // 响应返回的 headers
// }
const result = await payload.auth({ headers, canSetHeaders: false })
登录
// 返回结果格式如下:
// {
// token: 'o38jf0q34jfij43f3f...', // 用于身份验证的 JWT
// user: { ... } // 刚刚登录的用户文档
// exp: 1609619861 // JWT 过期时间的 UNIX 时间戳
// }
const result = await payload.login({
collection: 'users', // 必填
data: {
// 必填
email: 'dev@payloadcms.com',
password: 'rip',
},
req: req, // 可选,传递一个 Request 对象给所有钩子
depth: 2,
locale: 'en',
fallbackLocale: false,
overrideAccess: false,
showHiddenFields: true,
})
忘记密码
// 返回的 token 可用于重置密码
const token = await payload.forgotPassword({
collection: 'users', // 必填
data: {
// 必填
email: 'dev@payloadcms.com',
},
req: req, // 传递一个 Request 对象给所有钩子
})
重置密码
// 返回结果格式如下:
// {
// token: 'o38jf0q34jfij43f3f...', // 用于身份验证的 JWT
// user: { ... } // 刚刚登录的用户文档
// }
const result = await payload.resetPassword({
collection: 'users', // 必填
data: {
// 必填
password: req.body.password, // 要设置的新密码
token: 'afh3o2jf2p3f...', // 从 forgotPassword 操作生成的 token
},
req: req, // 可选,传递一个 Request 对象给所有钩子
})
解锁
// 返回结果是一个布尔值,表示操作成功或失败
const result = await payload.unlock({
collection: 'users', // 必填
data: {
// 必填
email: 'dev@payloadcms.com',
},
req: req, // 可选,传递一个 Request 对象给所有钩子
overrideAccess: true,
})
验证
// 返回结果将是一个布尔值,表示成功或失败
const result = await payload.verifyEmail({
collection: 'users', // 必填
token: 'afh3o2jf2p3f...', // 保存在用户上的 `_verificationToken` 令牌
})
全局数据
以下全局数据操作可通过 Local API 使用:
查找#global-find
// 结果将是 Header 全局数据。
const result = await payload.findGlobal({
slug: 'header', // 必填
depth: 2,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
showHiddenFields: true,
})
更新#global-update
// 结果将是更新后的 Header 全局数据。
const result = await payload.updateGlobal({
slug: 'header', // 必填
data: {
// 必填
nav: [
{
url: 'https://google.com',
},
{
url: 'https://payloadcms.com',
},
],
},
depth: 2,
locale: 'en',
fallbackLocale: false,
user: dummyUser,
overrideAccess: false,
overrideLock: false, // 默认情况下会忽略文档锁定。设置为 false 以强制执行锁定。
showHiddenFields: true,
})
TypeScript
Local API 调用会自动推断你的生成类型。
以下是使用示例:
// 会被正确推断为 `Post` 类型
const post = await payload.create({
collection: 'posts',
// 现在 data 将被类型化为 Post 并提供类型提示
data: {
title: 'my title',
description: 'my description',
},
})