Salesforce 开发人员体验如何改变您的工作方式

Salesforce 开发人员体验 (DX) 是一种在 Lightning Platform 贯穿其整个生命周期。它汇集了最好的 Lightning 平台可实现源代码驱动的开发、团队协作和治理、 以及 Salesforce 上自定义应用程序开发的敏捷性达到新的水平。

Salesforce DX 的亮点包括:

  • 您的工具,您的方式。借助 Salesforce DX,您可以使用已有的开发人员工具 知道。
  • 将最佳实践应用于软件开发的能力。源代码和 元数据存在于组织外部,为开发 Salesforce 提供了更高的敏捷性 团队环境中的应用。您的版本控制系统不是组织,而是 真相的来源。
  • 强大的命令行界面 (CLI) 消除了使用 用于开发、持续集成和交付的 Salesforce 组织。
  • 灵活且可配置的临时组织,用于开发和自动化 环境。这种新型组织使构建应用程序和 包。
  • 您可以将所需的任何 IDE 或文本编辑器与 CLI 一起使用,并外部化 源。
  • 适用于 VS Code 的 Salesforce 扩展 加速应用开发。这些工具提供了用于处理临时操作的功能 orgs、Apex、Lightning 组件和 Visualforce。

注意

Salesforce DX 工具需要启用 API 的系统权限,该权限提供 以编程方式访问组织的信息。

你准备好开始了吗?

以下是使用 Salesforce DX 完成工作的基本顺序。这些工作流 包括最常见的 CLI 命令。有关所有命令,请参阅 Salesforce CLI 命令参考。

  • 安装 Salesforce 命令行界面
  • 启用 Dev Hub
  • 使用示例 Repo 开始使用
  • 创建一个 应用
  • 迁移或 导入现有源
  • 使用示例存储库开始使用
    Salesforce DX 工具的最快方法是克隆 GitHub 存储库。使用其配置文件和 Salesforce 应用程序尝试一些常用的 Salesforce CLI 命令。除了应用程序的源代码外,存储库还包括示例数据和 Apex 测试。dreamhouse-lwc
  • 创建应用程序
    从头开始创建和开发在 Lightning 平台上运行的应用程序时,请遵循基本工作流程。
  • 迁移或导入现有源
    使用元数据 API 检索代码,然后转换源以在 Salesforce DX 项目中使用。
  • Salesforce DX 发行说明 使用 Salesforce 发行说明
    了解开发环境、打包、平台开发工具和 Salesforce API 的最新更新和更改。

使用示例存储库开始使用

使用 Salesforce DX 工具的最快方法是克隆 GitHub 存储库。使用其配置文件和 Salesforce应用程序尝试一些常用的Salesforce CLI命令。除了 应用程序的源代码,存储库包括示例数据和 Apex 测试。

dreamhouse-lwc

  1. 打开终端或命令提示符窗口,克隆 dreamhouse-lwc GitHub 使用 HTTPS 或 SSH 的示例存储库。
    HTTPS地址:git clone https://github.com/trailheadapps/dreamhouse-lwc.git
    SSH:git clone git@github.com:trailheadapps/dreamhouse-lwc.git
  2. 更改 dreamhouse-lwc 项目 目录。cd dreamhouse-lwc
  3. 授权您的 开发 Hub 组织,将其设置为默认值,然后 为其分配一个别名。
  4. sf org login web --set-default-dev-hub --alias DevHub在打开的浏览器中输入开发人员中心组织凭据。登录后 成功后,您可以关闭浏览器。
  5. 使用 config/project-scratch-def.json 文件创建一个临时组织,将该组织设置为 default,并为其分配一个别名。sf org create scratch --definition-file config/project-scratch-def.json --set-default --alias my-scratch-org该命令使用在上一个命令中设置的默认 Dev Hub 步。sf org login web
  6. 查看您已创建或登录的组织。sf org list第一个表显示你登录的 Dev Hub,第二个表显示 显示您创建的临时组织。两个表中最右边的一列 分别用 和 表示默认临时组织和 Dev Hub 组织。ALIAS 列显示 U 的别名 分配了每个组织。下面是一些示例输出。(U)(D)Non-scratch orgs ======================================================================================== | ALIAS USERNAME ORG ID CONNECTED STATUS | ─── ────── ────────────────────────────────────────── ────────────── ──────────────── | (D) DevHub jules@sf.com 00DB0000000c7j Connected Scratch orgs ============================================================================== | ALIAS USERNAME ORG ID EXPIRATION DATE | ─── ────────────── ───────────────────────── ────────────── ─────────────── | (U) my-scratch-org test-ibnpzayw@example.com 00D9A000000EFo 2023-05-12
  7. 将源位于 force-app 目录中的 Dreamforce 应用程序部署到临时组织。sf project deploy start --source-dir force-app
  8. 将 dreamhouse 权限集分配给 默认的临时组织用户 (test-ibnpzayw@example.com)。sf org assign permset --name dreamhouse
  9. 将示例数据从三个对象(Contact、Property 和 Broker)导入到 使用指定的计划定义文件临时组织。sf data import tree --plan data/sample-data-plan.json
  10. 运行 Apex 测试。sf apex run test --result-format human --wait 1默认情况下,Apex 测试以异步方式运行。如果测试在该值之前完成,则显示结果。 否则,请使用显示的命令通过作业 ID 获取结果。–wait
  11. 打开临时组织,并在“最近”下查看已部署的元数据 使用。sf org open
  12. 在应用程序启动器中,找到并打开 Dreamhouse 应用程序。

恭喜!您刚刚将应用程序部署到了一个新的临时组织。

创建应用程序

从头开始创建和开发 在 Lightning 平台上运行的应用程序。

  1. 设置你的 项目。
  2. 授权 Developer Hub 组织 项目。
  3. 配置本地 项目。
  4. 创建一个 Scratch 组织。
  5. 按下 从您的项目到 Scratch 组织。
  6. 开发应用。
  7. 拉取 source 使您的项目和 Scratch 组织保持同步。
  8. 运行测试。
  9. 添加、提交和推送更改。创建拉取请求。

使用以下方法之一部署应用:

  • 构建和 使用托管包发布应用
  • 生成和发布 使用元数据 API 的应用

迁移或导入现有源

使用元数据 API 检索代码,然后转换源代码以在 Salesforce DX 项目。

提示

如果当前存储库遵循从 元数据 API 检索,可以跳过检索步骤,直接进行转换 源。

  1. 设置你的 项目。
  2. 检索元数据。
  3. 将 您刚刚检索到的元数据格式的源。
  4. 授权 Developer Hub 组织 项目。
  5. 配置本地 项目。
  6. 创建一个 Scratch 组织。
  7. 按下 从您的项目到 Scratch 组织。
  8. 开发应用。
  9. 拉取 source 来同步您的项目和 Scratch 组织。
  10. 运行测试。
  11. 添加、提交和推送更改。创建拉取请求。

使用以下方法之一部署应用:

  • 使用托管包生成和发布应用。
  • 建 并使用元数据 API 发布您的应用。

Salesforce DX 发行说明

使用 Salesforce 发行说明了解 开发环境、打包、平台开发工具和 Salesforce 蜜蜂属。

有关最新更改,请访问:

  • Salesforce Extensions for Visual Studio Code 发行说明
  • Salesforce CLI 版本 笔记
  • 开发环境发布 注释(包括 Developer Edition 组织、沙箱和临时组织)
  • 打包发行说明
  • 面向开发人员的新项目和更改项目(包括 Apex、标准对象、元数据 API 等)

在组织中启用 Dev Hub 功能

在 PBO 中启用 Dev Hub 功能,以便创建和管理临时组织,创建 并管理第二代软件包,并使用 Einstein 功能。Scratch 组织是一次性的 Salesforce 组织来支持开发和测试。

在 PBO 中启用 Dev Hub 是安全的,不会导致任何性能或客户问题。开发 Hub 包含具有权限的对象,这些权限允许管理员控制访问级别 可供用户和组织使用。

注意

无法在沙盒中启用 Dev Hub。

如果选择试用版或 Developer Edition 组织作为开发人员中心,请考虑这些因素。

  • 您每天最多可以创建 6 个临时组织和软件包版本,最多可以创建 3 个 活跃的临时组织。
  • 试用组织在其到期日期到期。
  • Developer Edition 组织可能会因不活动而过期。
  • 可以在不是 Dev Hub 的 Developer Edition 组织中定义命名空间,并且可以 在不包含命名空间的 Developer Edition 组织中启用 Dev Hub。
  • 如果计划创建包版本或运行持续集成作业,最好 使用 PBO 作为开发人员中心,因为临时组织和包版本限制更高。包 版本与开发人员中心组织相关联。当试用版或 Developer Edition 组织到期时, 您将无法访问包版本。

注意

从合作伙伴社区注册的合作伙伴试用组织具有不同的暂存组织限制。 请参阅合作伙伴的临时组织分配。 合作伙伴可以创建合作伙伴版临时组织:合作伙伴开发人员、合作伙伴企业、合作伙伴 组和合作伙伴专业人员。仅当从 合作伙伴业务组织中的 Dev Hub。有关详细信息,请参阅《第一代托管打包开发人员指南》中的合作伙伴支持的 Scratch 组织版本。

Dev Hub 组织实例确定临时组织的创建位置。

  • 从政府云中的开发人员中心组织创建的临时组织是在政府上创建的 云实例。
  • 从公有云中的 Dev Hub 组织创建的临时组织是在公有云上创建的 实例。

若要在组织中启用 Dev Hub,请执行以下操作:

  1. 以系统管理员身份登录到 Developer Edition、试用版或生产组织(对于 客户)或业务组织(适用于 ISV)。
  2. 在“设置”中,在“快速查找”框中输入“开发人员中心”,然后选择“开发人员中心”。如果在“设置”菜单中未看到“开发人员中心”,请确保你的组织是受支持的组织之一 版本。
  3. 若要启用 Dev Hub,请单击“启用”。启用 Dev Hub 后,无法禁用它。
  • 免费有限访问许可证
    申请 Salesforce 有限访问权限 – 免费许可证,用于向生产组织中的非管理员用户提供帐户,当这些用户只需要访问特定应用程序、功能或设置时。此许可证无法访问标准 Salesforce 对象,例如客户、联系人和商机。
  • 启用解锁和第二代托管打包 在组织中启用打包
    ,以便可以开发解锁包或第二代托管包。您可以在临时组织、沙盒组织和目标订阅者组织中使用软件包。
  • 沙盒
    中启用源跟踪 在源(生产)组织中启用源跟踪,以便 Developer 和 Developer Pro 沙盒自动跟踪从它创建的沙盒和 Salesforce DX 项目之间的更改。现有沙盒在刷新之前不会启用源跟踪。
  • 启用 Einstein 功能
    在开发人员中心打开 Einstein 功能,以消除在临时组织中启用聊天机器人功能的手动步骤。当您接受 Einstein 的服务条款时,从此 Dev Hub 组织创建的每个临时组织都不需要单独接受。如果您之前接受了 Einstein 的服务条款以启用与 Einstein 相关的功能,则此设置已启用。
  • 启用语言扩展包 (Beta)
    在开发人员中心启用语言扩展包,以创建包含其他包中组件翻译的语言扩展包。此功能在未锁定的包以及第一代和第二代托管包中可用。
  • 添加 Salesforce DX 用户
    默认情况下,系统管理员可以访问 Dev Hub 组织。您可以允许更多用户访问 Dev Hub 组织,以便他们可以创建临时组织并使用其他特定于开发人员的功能。

免费有限访问许可证

申请 Salesforce 有限访问权限 – 向非管理员用户提供帐户的免费许可证 在您的生产组织中,当这些用户只需要访问特定应用、功能或 设置。标准 Salesforce 对象(如客户、联系人和商机)不是 可通过此许可证访问。

请联系您的 Salesforce 客户经理申请此许可证。Salesforce 管理员可以 将 Salesforce Limited Access – Free 许可证升级为标准 Salesforce 许可证 时间。

第二代托管软件包和解锁软件包

要创建临时组织和解锁或第二代托管软件包,开发人员 需要访问开发人员中心组织,这通常是生产组织。销售团队 然后,管理员可以向 Dev Hub 对象 (ScratchOrgInfo、 ActiveScratchOrg 和 NamespaceRegistry)。

若要为开发人员提供对开发人员中心组织的适当访问权限,请创建一个权限集,该权限集 包含以下权限:

  • 对象设置 >临时组织信息 >读取、创建和删除
  • “活动临时组织”>对象设置>读取和删除
  • “命名空间注册表>读取”>对象设置(在 Scratch 组织)

为用户提供创建解锁或第二代托管的能力 包和包版本,权限集还必须包含:

  • 创建和更新第二代软件包>系统权限

如果您选择在临时组织中测试软件包,则 创建和更新 在以下情况下,创建临时组织时也需要第二代软件包权限 您在 sfdx-project.json 文件中指定了祖先版本。 或者,将 –noancestors 标志与 sf org 一起使用 create 命令。

有关更多信息,请参阅 Salesforce DX 开发人员指南:添加 Salesforce DX 用户。

DevOps中心

DevOps Center 作为托管包安装。大多数团队成员,例如构建者和 开发人员,无需安装和配置 DevOps Center。您可以提供这些 团队成员通过分配 他们此许可证和有限访问用户配置文件。

请参阅 Salesforce 帮助:分配 DevOps Center 权限集

当前不支持的功能

  • 要将组织形状用于临时组织或临时组织快照(试点),请务必 分配 Salesforce 用户许可证。Salesforce 有限访问 – 免费许可证 目前不支持。
  • Salesforce 有限访问 – 免费许可证不提供对某些 Salesforce CLI 命令,例如 .请联系您的 Salesforce 管理员,了解 API 限制信息。sf limits api display

启用解锁和第二代托管打包

在组织中启用打包,以便开发未锁定的包或第二代 托管包。您可以在临时组织、沙盒组织和目标中使用软件包 订阅者组织。

在组织中启用 Dev Hub。

  1. 登录到已启用 Dev Hub 的组织。
  2. 在“设置”中,在“快速查找”框中输入“开发人员中心”,然后选择“开发人员中心”。
  3. 选择“启用解锁包”和“第二代托管” 包。启用第二代打包后,无法禁用它。
  4. (可选)允许非管理员用户访问开发人员中心以创建包。为非管理员用户分配“创建和更新第二代包”用户权限。 有关详细信息,请参阅添加 Salesforce DX 用户。

在沙盒中启用源跟踪

在源(生产)组织中启用源跟踪,以便 Developer 和 Developer Pro 沙盒会自动跟踪从它创建的沙盒和 Salesforce DX 之间的更改 项目。在刷新之前,现有沙盒不会启用源跟踪 他们。

所需的用户权限
要查看沙盒,请执行以下操作:View 设置和配置
要创建、刷新、激活和删除沙盒,请执行以下操作:管理沙盒
要启用源跟踪,请执行以下操作:自定义应用程序

要在 Sandboxes for Developer 和 Developer Pro 沙盒中启用源跟踪,请执行以下操作:

  1. 登录到源(生产)组织。
  2. 在“设置”的“快速查找”框中,输入“开发人员中心”,然后选择“开发人员中心”。如果在“设置”菜单中未看到“Dev Hub”,请确保源组织是 支持的版本。
  3. 在 Developer 和 Developer Pro 中选择“启用源跟踪” 沙盒
  4. 刷新任何现有的 Developer 或 Developer Pro 沙盒以启用此功能。系统会自动为任何新创建的开发人员或开发人员启用源跟踪 专业沙盒。

启用 Einstein 功能

在开发人员中心中打开 Einstein 功能,以消除启用 临时组织中的聊天机器人功能。当您接受 Einstein 服务条款时, 从此 Dev Hub 组织创建的每个临时组织不需要单独接受。如果 您之前已接受 Einstein 的服务条款,以开启 Einstein 相关的 功能,此设置已启用。

在尝试使用聊天机器人创建临时组织之前,请完成此任务 特征。

  1. 登录到开发人员中心组织。
  2. 在“设置”中,在“快速查找”框中输入“开发人员中心”,然后 选择“开发人员中心”。
  3. 在“Dev Hub 设置”页上,打开“启用 Einstein” 特征

启用语言扩展包(测试版)

在开发人员中心启用语言扩展包,以创建语言扩展包 包含其他包中组件的翻译。此功能在解锁和 第一代和第二代托管包。

注意

此功能是一项测试版服务。客户可以选择单独试用此类测试版服务 自由裁量权。对测试版服务的任何使用均受适用的测试版服务条款的约束 在协议和条款中提供。

语言扩展包只能包含 Translations 和 CustomObjectTranslations。如果 基础包包含无法翻译的组件,这些组件在以下情况下不包括在内 创建语言扩展包。

  1. 在“开发人员中心”的“设置”中,在“快速查找”框中,输入“开发人员中心”,然后 然后选择“开发人员中心”。
  2. 在“开发人员中心设置”页上,打开“启用语言扩展” 包

添加 Salesforce DX 用户

默认情况下,系统管理员可以访问 Dev Hub 组织。您可以启用更多用户 访问 Dev Hub 组织,以便他们可以创建临时组织并使用其他 特定于开发人员的功能。

您可以将 Salesforce DX 与以下标准用户许可证一起使用:Salesforce、Salesforce 平台和开发人员。

如果您的组织具有开发人员许可证,则可以使用开发人员配置文件添加用户,然后 为他们分配提供的开发人员权限集。或者,您可以添加用户 使用标准用户或系统管理员配置文件。对于标准用户,您 必须创建具有所需 Salesforce DX 权限的权限集。我们 建议您避免将用户添加为系统管理员,除非他们的工作 需要该级别的权限,而不仅仅是 Dev Hub 组织访问权限。

  • 将开发人员用户添加到开发人员中心组织
    使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配开发人员权限集。
  • 将系统管理员或标准用户添加到开发人员中心组织
    仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。否则,请添加标准用户并创建具有所需 Salesforce DX 权限的权限集。
  • Salesforce DX 用户的
    权限集 要授予对开发人员中心组织的完全访问权限,您创建的开发人员权限集或自定义权限集将授予对特定 Salesforce DX 对象的访问权限。

将开发人员用户添加到开发人员中心组织

使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配 开发人员权限集。

  1. 在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表格。
    4. 选择“开发人员”作为“用户许可证”,然后选择“开发人员”作为“配置文件”。
    5. 填写完剩余信息后,单击“保存”。
  2. 将内置的“开发人员”权限集分配给用户。
    1. 在用户详细信息页上的“权限集分配”相关列表中,单击“编辑分配”。
    2. 在“可用权限集”中,添加“开发人员”权限集,然后单击“保存”。

开发人员权限集授予对 Dev Hub 功能和第二代包的访问权限。 有关详细信息,请参阅 Salesforce DX 用户的权限集。

将系统管理员或标准用户添加到开发人员中心 组织

仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。 否则,请添加标准用户并使用所需的 Salesforce DX 创建权限集 权限。

  1. 如有必要,请在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表单,并分配“系统管理员”或“标准用户”配置文件。
    4. 点击保存
    如果要添加系统管理员用户,则可以在此处停止。
  2. 如果您要添加标准用户,请为 Salesforce DX 用户创建权限集(如果没有) 有一个。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 单击“新建”。
    3. 输入标签、API 名称和描述。API 名称是 API 使用的唯一名称,并且 托管包。
    4. 选择用户许可证选项。如果计划将此权限集分配给具有不同许可证的多个用户,请选择“”。
    5. 点击保存。此时将显示权限集概述页面。从这里,您可以 导航到要为 Salesforce DX 添加或更改的权限。 有关所需权限,请参阅 Salesforce DX 用户的权限集。
  3. 将 Salesforce DX 权限集应用于标准用户。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 选择 Salesforce DX 权限集。
    3. 在权限集工具栏中,单击“管理分配”。
    4. 单击“添加分配”。
    5. 选择要向其分配权限集的用户。
    6. 单击分配
    7. 单击完成

您可以通过修改权限来限制用户的访问权限。

Salesforce DX 用户的权限集

若要授予对开发人员中心组织的完全访问权限,请执行开发人员权限集或自定义权限 您创建的权限集授予对特定 Salesforce DX 对象的访问权限。

  • 对象设置 >临时组织信息 >读取、创建、编辑和删除
  • 活动临时组织>对象设置>读取、编辑和删除
  • 对象设置>命名空间注册表>读取

若要在开发人员中心组织中使用第二代包,权限集还必须 包含:

  • 创建和更新第二代软件包>系统权限

此权限提供对以下内容的访问:

Salesforce CLI 命令工具 API 对象(创建和编辑)
package create套餐2
package version createPackage2VersionCreateRequest
package version updatePackage2版本

将开发人员用户添加到开发人员中心组织

使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配 开发人员权限集。

  1. 在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表格。
    4. 选择“开发人员”作为“用户许可证”,然后选择“开发人员”作为“配置文件”。
    5. 填写完剩余信息后,单击“保存”。
  2. 将内置的“开发人员”权限集分配给用户。
    1. 在用户详细信息页上的“权限集分配”相关列表中,单击“编辑分配”。
    2. 在“可用权限集”中,添加“开发人员”权限集,然后单击“保存”。

开发人员权限集授予对 Dev Hub 功能和第二代包的访问权限。 有关详细信息,请参阅 Salesforce DX 用户的权限集。

将系统管理员或标准用户添加到开发人员中心 组织

仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。 否则,请添加标准用户并使用所需的 Salesforce DX 创建权限集 权限。

  1. 如有必要,请在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表单,并分配“系统管理员”或“标准用户”配置文件。
    4. 点击保存
    如果要添加系统管理员用户,则可以在此处停止。
  2. 如果您要添加标准用户,请为 Salesforce DX 用户创建权限集(如果没有) 有一个。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 单击“新建”。
    3. 输入标签、API 名称和描述。API 名称是 API 使用的唯一名称,并且 托管包。
    4. 选择用户许可证选项。如果计划将此权限集分配给具有不同许可证的多个用户,请选择“”。
    5. 点击保存。此时将显示权限集概述页面。从这里,您可以 导航到要为 Salesforce DX 添加或更改的权限。 有关所需权限,请参阅 Salesforce DX 用户的权限集。
  3. 将 Salesforce DX 权限集应用于标准用户。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 选择 Salesforce DX 权限集。
    3. 在权限集工具栏中,单击“管理分配”。
    4. 单击“添加分配”。
    5. 选择要向其分配权限集的用户。
    6. 单击分配
    7. 单击完成

您可以通过修改权限来限制用户的访问权限。

Salesforce DX 用户的权限集

若要授予对开发人员中心组织的完全访问权限,请执行开发人员权限集或自定义权限 您创建的权限集授予对特定 Salesforce DX 对象的访问权限。

  • 对象设置 >临时组织信息 >读取、创建、编辑和删除
  • 活动临时组织>对象设置>读取、编辑和删除
  • 对象设置>命名空间注册表>读取

若要在开发人员中心组织中使用第二代包,权限集还必须 包含:

  • 创建和更新第二代软件包>系统权限

此权限提供对以下内容的访问:

Salesforce CLI 命令工具 API 对象(创建和编辑)
package create套餐2
package version createPackage2VersionCreateRequest
package version updatePackage2版本

添加 Salesforce DX 用户

默认情况下,系统管理员可以访问 Dev Hub 组织。您可以启用更多用户 访问 Dev Hub 组织,以便他们可以创建临时组织并使用其他 特定于开发人员的功能。

您可以将 Salesforce DX 与以下标准用户许可证一起使用:Salesforce、Salesforce 平台和开发人员。

如果您的组织具有开发人员许可证,则可以使用开发人员配置文件添加用户,然后 为他们分配提供的开发人员权限集。或者,您可以添加用户 使用标准用户或系统管理员配置文件。对于标准用户,您 必须创建具有所需 Salesforce DX 权限的权限集。我们 建议您避免将用户添加为系统管理员,除非他们的工作 需要该级别的权限,而不仅仅是 Dev Hub 组织访问权限。

  • 将开发人员用户添加到开发人员中心组织
    使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配开发人员权限集。
  • 将系统管理员或标准用户添加到开发人员中心组织
    仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。否则,请添加标准用户并创建具有所需 Salesforce DX 权限的权限集。
  • Salesforce DX 用户的
    权限集 要授予对开发人员中心组织的完全访问权限,您创建的开发人员权限集或自定义权限集将授予对特定 Salesforce DX 对象的访问权限。

将开发人员用户添加到开发人员中心组织

使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配 开发人员权限集。

  1. 在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表格。
    4. 选择“开发人员”作为“用户许可证”,然后选择“开发人员”作为“配置文件”。
    5. 填写完剩余信息后,单击“保存”。
  2. 将内置的“开发人员”权限集分配给用户。
    1. 在用户详细信息页上的“权限集分配”相关列表中,单击“编辑分配”。
    2. 在“可用权限集”中,添加“开发人员”权限集,然后单击“保存”。

开发人员权限集授予对 Dev Hub 功能和第二代包的访问权限。 有关详细信息,请参阅 Salesforce DX 用户的权限集。

将系统管理员或标准用户添加到开发人员中心 组织

仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。 否则,请添加标准用户并使用所需的 Salesforce DX 创建权限集 权限。

  1. 如有必要,请在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表单,并分配“系统管理员”或“标准用户”配置文件。
    4. 点击保存
    如果要添加系统管理员用户,则可以在此处停止。
  2. 如果您要添加标准用户,请为 Salesforce DX 用户创建权限集(如果没有) 有一个。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 单击“新建”。
    3. 输入标签、API 名称和描述。API 名称是 API 使用的唯一名称,并且 托管包。
    4. 选择用户许可证选项。如果计划将此权限集分配给具有不同许可证的多个用户,请选择“”。
    5. 点击保存。此时将显示权限集概述页面。从这里,您可以 导航到要为 Salesforce DX 添加或更改的权限。 有关所需权限,请参阅 Salesforce DX 用户的权限集。
  3. 将 Salesforce DX 权限集应用于标准用户。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 选择 Salesforce DX 权限集。
    3. 在权限集工具栏中,单击“管理分配”。
    4. 单击“添加分配”。
    5. 选择要向其分配权限集的用户。
    6. 单击分配
    7. 单击完成

您可以通过修改权限来限制用户的访问权限。

Salesforce DX 用户的权限集

若要授予对开发人员中心组织的完全访问权限,请执行开发人员权限集或自定义权限 您创建的权限集授予对特定 Salesforce DX 对象的访问权限。

  • 对象设置 >临时组织信息 >读取、创建、编辑和删除
  • 活动临时组织>对象设置>读取、编辑和删除
  • 对象设置>命名空间注册表>读取

若要在开发人员中心组织中使用第二代包,权限集还必须 包含:

  • 创建和更新第二代软件包>系统权限

此权限提供对以下内容的访问:

Salesforce CLI 命令工具 API 对象(创建和编辑)
package create套餐2
package version createPackage2VersionCreateRequest
package version updatePackage2版本

添加 Salesforce DX 用户

默认情况下,系统管理员可以访问 Dev Hub 组织。您可以启用更多用户 访问 Dev Hub 组织,以便他们可以创建临时组织并使用其他 特定于开发人员的功能。

您可以将 Salesforce DX 与以下标准用户许可证一起使用:Salesforce、Salesforce 平台和开发人员。

如果您的组织具有开发人员许可证,则可以使用开发人员配置文件添加用户,然后 为他们分配提供的开发人员权限集。或者,您可以添加用户 使用标准用户或系统管理员配置文件。对于标准用户,您 必须创建具有所需 Salesforce DX 权限的权限集。我们 建议您避免将用户添加为系统管理员,除非他们的工作 需要该级别的权限,而不仅仅是 Dev Hub 组织访问权限。

  • 将开发人员用户添加到开发人员中心组织
    使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配开发人员权限集。
  • 将系统管理员或标准用户添加到开发人员中心组织
    仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。否则,请添加标准用户并创建具有所需 Salesforce DX 权限的权限集。
  • Salesforce DX 用户的
    权限集 要授予对开发人员中心组织的完全访问权限,您创建的开发人员权限集或自定义权限集将授予对特定 Salesforce DX 对象的访问权限。

将开发人员用户添加到开发人员中心组织

使用开发人员许可证,添加具有开发人员配置文件的用户,并为其分配 开发人员权限集。

  1. 在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表格。
    4. 选择“开发人员”作为“用户许可证”,然后选择“开发人员”作为“配置文件”。
    5. 填写完剩余信息后,单击“保存”。
  2. 将内置的“开发人员”权限集分配给用户。
    1. 在用户详细信息页上的“权限集分配”相关列表中,单击“编辑分配”。
    2. 在“可用权限集”中,添加“开发人员”权限集,然后单击“保存”。

开发人员权限集授予对 Dev Hub 功能和第二代包的访问权限。 有关详细信息,请参阅 Salesforce DX 用户的权限集。

将系统管理员或标准用户添加到开发人员中心 组织

仅当系统管理员用户的工作需要该级别的权限时,才添加系统管理员用户。 否则,请添加标准用户并使用所需的 Salesforce DX 创建权限集 权限。

  1. 如有必要,请在 Dev Hub 组织中创建用户。
    1. 在“设置”中,在“快速查找”框中输入“用户”,然后选择“用户”。
    2. 单击“新建用户”。
    3. 填写表单,并分配“系统管理员”或“标准用户”配置文件。
    4. 点击保存
    如果要添加系统管理员用户,则可以在此处停止。
  2. 如果您要添加标准用户,请为 Salesforce DX 用户创建权限集(如果没有) 有一个。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 单击“新建”。
    3. 输入标签、API 名称和描述。API 名称是 API 使用的唯一名称,并且 托管包。
    4. 选择用户许可证选项。如果计划将此权限集分配给具有不同许可证的多个用户,请选择“”。
    5. 点击保存。此时将显示权限集概述页面。从这里,您可以 导航到要为 Salesforce DX 添加或更改的权限。 有关所需权限,请参阅 Salesforce DX 用户的权限集。
  3. 将 Salesforce DX 权限集应用于标准用户。
    1. 在“设置”中,在“快速查找”框中输入“权限集”,然后选择“权限集”。
    2. 选择 Salesforce DX 权限集。
    3. 在权限集工具栏中,单击“管理分配”。
    4. 单击“添加分配”。
    5. 选择要向其分配权限集的用户。
    6. 单击分配
    7. 单击完成

您可以通过修改权限来限制用户的访问权限。

Salesforce DX 用户的权限集

若要授予对开发人员中心组织的完全访问权限,请执行开发人员权限集或自定义权限 您创建的权限集授予对特定 Salesforce DX 对象的访问权限。

  • 对象设置 >临时组织信息 >读取、创建、编辑和删除
  • 活动临时组织>对象设置>读取、编辑和删除
  • 对象设置>命名空间注册表>读取

若要在开发人员中心组织中使用第二代包,权限集还必须 包含:

  • 创建和更新第二代软件包>系统权限

此权限提供对以下内容的访问:

Salesforce CLI 命令工具 API 对象(创建和编辑)
package create套餐2
package version createPackage2VersionCreateRequest
package version updatePackage2版本

项目设置

Salesforce DX 为组织的元数据(代码和 配置)、组织模板、示例数据以及团队的所有测试。为了保持一致性 团队的开发流程,将这些项目存储在源代码管理系统 (SCS) 中。取回 当您准备好开发新功能时,团队存储库的内容。

您可以使用您喜欢的 SCS。我们的大多数示例都使用 Git。

您有不同的选项来创建 Salesforce DX 项目,具体取决于您想要的方式 开始。

使用示例存储库 在 GitHub 上使用我们的一个示例存储库和您自己的 SCS 探索 Salesforce DX 的功能 和工具集。
创建一个 来自现有来源的 Salesforce DX 项目从现有的 Salesforce 应用程序开始,创建 Salesforce DX 项目。
创建一个 Salesforce DX 项目使用 Salesforce DX 项目在 Salesforce Platform 上创建应用程序。
  • GitHub 上的示例存储库 若要快速入门,请参阅 GitHub
    存储库。此独立应用程序包含一个示例 DX 项目,其中包含多个 Apex 类、Aura 组件、自定义对象、示例数据和 Apex 测试。dreamhouse-lwc
  • 创建 Salesforce DX 项目 Salesforce DX 项目
    具有特定的结构和将目录标识为 Salesforce DX 项目的配置文件。
  • Salesforce DX 项目结构和源格式 Salesforce DX 项目具有特定的项目结构和源格式
    。源格式使用与元数据 API 使用的文件和文件扩展名不同的一组文件和文件扩展名。当您使用命令从组织中检索元数据时,Salesforce CLI 会将其以源格式存储在您的项目中。当您部署元数据时,Salesforce CLI 会将其转换为元数据 API 所需的格式。project retrieve start
  • 同步时如何排除
    在本地文件系统和目标组织之间同步元数据时,通常有要排除的源文件。同样,在将源转换为 Salesforce DX 源格式时,您经常希望排除某些文件。在这两种情况下,您都可以使用文件排除特定目录中的单个文件或所有文件。.forceignore
  • 从现有源
    创建 Salesforce DX 项目 如果您是 Salesforce 开发人员、合作伙伴或 ISV,则您的打包组织中的托管包中可能有现有源,或者沙盒或生产组织中的应用程序源中可能有现有源。在开始使用 Salesforce DX 之前,请将现有源检索到 Salesforce DX 项目中。
  • 将元数据格式的文件转换为源格式
    如果您已经有一个存储库,其中您直接使用元数据 API 从组织中检索元数据,则这些文件采用元数据格式。您可以将这些文件转换为源格式,并将它们添加到您的 Salesforce DX 项目中。然后,您可以使用 CLI 命令在组织内部署和检索它们,并使用源跟踪来跟踪更改。
  • Salesforce DX 用户名和组织
    许多 Salesforce CLI 命令连接到组织以完成其任务。例如,创建临时组织的命令连接到开发人员中心组织。和命令在项目和组织之间同步源代码。在每种情况下,CLI 命令都需要用户名来确定要连接到哪个组织。用户名在整个 Salesforce 生态系统中是唯一的,并且仅与一个组织相关联。org create scratchproject deploy startproject retrieve start
  • 将命名空间链接到 Dev Hub 组织 要将命名空间与临时组织一起使用,必须将命名空间注册的 Developer Edition 组织链接到 Dev Hub 组织
  • Salesforce DX 项目配置
    项目配置文件 sfdx-project.json 表示该目录是 Salesforce DX 项目。配置文件包含项目信息,便于组织授权和创建第二代包。它还告诉 Salesforce CLI 在项目和组织之间同步时将文件放在哪里。
  • 多个包目录 创建 Salesforce DX 项目
    时,我们建议您通过在本地创建多个包目录,将元数据组织到逻辑分组中。然后,在文件中定义这些目录。您可以对应用程序或自定义项的类似代码和源代码进行分组,以更好地组织团队的存储库。稍后,如果您决定使用第二代软件包 (2GP),则这些目录对应于实际的 2GP 软件包。sfdx-project.json
  • 在部署
    之前替换代码中的字符串 在将文件部署到组织之前,自动将元数据源文件中的字符串替换为特定值。

GitHub 上的示例存储库

若要快速入门,请参阅 GitHub 存储库。此独立应用程序包含一个具有多个 Apex 的示例 DX 项目 类、Aura 组件、自定义对象、示例数据和 Apex 测试。

dreamhouse-lwc

克隆此存储库会创建目录 dreamhouse-lwc。有关详细信息,请参阅存储库的自述文件。

假设您已经设置了 Git,请使用该命令从命令行克隆存储库的 main 分支。git clone

要使用 HTTPS,请执行以下操作:

git clone https://github.com/trailheadapps/dreamhouse-lwc

要使用 SSH,请执行以下操作:

git clone git@github.com:trailheadapps/dreamhouse-lwc.git

如果您不想使用 Git.zip,请使用 克隆,或在 GitHub 网站上下载。解压缩本地文件上任意位置的源 系统。

有关后续步骤,请参阅使用示例存储库开始。

提示

在示例库中查看更复杂的示例。

示例库包含示例应用,这些应用显示了可以在 Salesforce平台。它们会不断更新以包含最新功能 和最佳实践。

创建 Salesforce DX 项目

Salesforce DX 项目具有特定的结构和配置文件,用于标识 目录作为 Salesforce DX 项目。

  1. 切换到 DX 项目所在的目录。
  2. 创建 DX 项目。sf project generate --name MyProject如果你 不要使用标志指定输出目录,项目目录将在当前位置创建。 您还可以使用该标志来 指定在将源同步到组织或从组织同步源时要作为目标的默认包目录。 如果未指示默认包目录,则此命令将创建默认包 目录,force-app。–output-dir–default-package-dir使用该标志指定项目的初始外观。每 模板提供了一个完整的目录结构,消除了猜测 把你的来源。如果选择 , 您的项目包含这些示例配置文件,可帮助您入门。–template–template empty
    • .forceignore
    • config/project-scratch-def.json
    • sfdx-project.json文件
    • package.json
    如果您选择 , 您的 project 还包含这些文件,这些文件在使用 Salesforce 时特别有用 VS Code 的扩展。如果未指定标志,则该命令将使用标准模板。–template standard–templateproject generate
    • .gitignore:使开始使用 Git 版本更容易 控制。
    • .prettierrc 和 .prettierignore:制作 更容易开始使用 Prettier 格式化您的 Aura 组件。
    • .vscode/extensions.json:当 launched,提示您为项目安装推荐的扩展。
    • .vscode/launch.json:配置重播调试器,使其更 可发现且更易于使用。
    • .vscode/settings.json:默认情况下,此文件有一个设置 用于在搜索和快速打开中排除某些文件和文件夹。您可以更改 此值或添加其他设置。
    如果你选择 ,你会得到 所有有用的基本文件和 VS Code 文件。但是默认的包目录包含 更少的目录,例如用于存储 Analytics 模板包的目录。/force-app/main/default/waveTemplates)和其他一些元数据 类型,例如 Apex 类和 LWC 组件。–template analytics

sf project generate --name mywork --template standard
sf project generate --name mywork --default-package-dir myapp-source

后续步骤:

  • (可选)将命名空间注册到 Dev Hub 组织。
  • 配置项目 (sfdx-project.json)。如果使用命名空间, 更新此文件以包含它。
  • 创建一个临时组织定义,以生成具有所需功能的临时组织 为您的项目。新项目的 config 目录包含一个 暂存组织定义文件 (project-scratch-def.json) 示例。

Salesforce DX 项目结构和来源 格式

Salesforce DX 项目具有特定的项目结构和源格式。源 format 使用与元数据 API 使用的文件和文件扩展名不同的一组文件和文件扩展名。 当您使用命令从组织中检索元数据时,Salesforce CLI 会将其以源格式存储在 项目。当您部署元数据时,Salesforce CLI 会将其转换为 元数据 API 需要。

project retrieve start

源转换

元数据格式化的情况并不少见 来源非常大,很难找到你想要的东西。如果你在 与同时更新相同元数据的其他开发人员合作,您拥有 以处理将多个更新合并到文件。如果你认为有 为了更好的方式,你是对的。

之前,所有自定义对象和对象 翻译存储在一个大型元数据文件中。

我们通过提供一种新的源形状来分解这些问题 大型源文件,使其更易于消化,更易于使用版本进行管理 控制系统。它被称为源格式。

Salesforce DX 项目存储 直观子目录中的自定义对象和自定义对象转换。源 格式化使查找要更改或更新的内容变得更加容易。你可以 告别凌乱的合并。

静态资源

静态资源必须位于 /main/default/staticresources 目录中。和命令支持自动扩展或压缩 在项目中存档 MIME 类型。这些行为支持 .zip 和 .jar MIME 类型。这边 源文件可以更轻松地集成到您的 Salesforce DX 项目中,并且 版本控制系统。project deployproject retrieve

例如,如果您上传静态资源存档 通过临时组织的设置 UI,该命令将其扩展为 项目。要从文件系统模拟此过程,请将目录结构添加到 直接压缩到 static resources 目录根目录,然后创建 关联的 .resource-meta.xml 文件。如果存档以 单个文件,则始终将其视为单个文件,而不是 扩大。project retrieve start

此示例说明了不同类型的静态资源是如何 存储在本地项目中。您可以看到名为 expandedzippedresource 的扩展 .zip 存档及其相关的 .resource-meta.xml 文件。您还会看到几个 .jpg 文件与其 MIME 类型一起存储,以及一个 以旧版 .resource 扩展名存储的文件

有关更多信息,请参阅 Salefsorce 帮助:静态资源 信息。

文件扩展名

当您将现有元数据格式转换为源格式时,我们会为 每个位。现在,所有包含 XML 标记的文件都具有 .xml 扩展名,以便 XML 编辑器将它们识别为 XML 文件,您可以查看 他们。要同步本地项目和临时组织,Salesforce DX 项目使用 自定义对象的特定目录结构、自定义对象转换、 Lightning Web 组件、Aura 组件和文档。

例如,如果您有一个名为 Case 的对象,则源格式将提供 XML 版本 称为 Case.object-meta.xml。如果您有一个名为 DreamHouse,我们创建一个名为 DreamHouse.app-meta.xml 的文件。 你明白了。

传统上,静态资源作为二进制对象存储在文件系统上,具有 .resource 扩展名。源格式处理静态资源 通过支持内容 MIME 类型而有所不同。例如,.gif 文件存储为 .gif 而不是 .resource。通过存储带有 MIME 扩展名的文件,您可以 可以使用系统上的相关编辑器管理和编辑文件。

您可以将现有静态资源及其 .resource 扩展名与新创建的静态资源组合在一起 及其 MIME 内容扩展。具有 .resource 扩展名的现有静态资源将保留该扩展名,但任何新的 静态资源以其 MIME 类型扩展名显示在项目中。我们允许 .resource 文件支持现有 客户。虽然您可以获得这种额外的灵活性,但我们建议您存储您的 文件及其 MIME 扩展名。

自定义对象

当您从元数据格式转换为源格式时,您的自定义 对象放置在 <package 中 目录>/main/default/objects 目录。每个对象 具有自己的子目录,用于反映自定义对象的类型。某些部分 自定义对象被提取到以下子目录中:

  • 业务流程
  • 紧凑型布局
  • 领域
  • 字段集
  • 列表视图
  • 记录类型
  • sharing原因
  • validationRules
  • 网页链接

未提取的自定义对象部分放置在 <object>.object-meta.xml 文件中。

自定义对象翻译

自定义对象转换 驻留在<包中 目录>/main/default/objectTranslations 目录, 每个子目录都位于以自定义对象转换命名的子目录中。习惯 对象转换和字段转换被提取到它们自己的文件中 自定义对象转换的目录。

  • 对于字段名称,请<field_name>.fieldTranslation-meta.xml
  • 对于对象名称,请<object_name>.objectTranslation-meta.xml

自定义对象转换中未完成的其余部分 字段翻译放置在名为 <objectTranslation>.objectTranslation-meta.xml 的文件中。

请参阅 Salesforce 帮助:Translation Workbench 更多信息。

Aura 组件

Aura 捆绑包和组件必须位于 <package 下名为 aura 的目录 目录>目录。

Lightning Web 组件

Lightning Web 组件必须位于 <package 下名为 lwc 的目录 目录>目录。

适用于 Lightning 社区的 ExperienceBundle

ExperienceBundle 元数据类型必须位于 <package 下名为 experiences 的目录中 目录>目录。experiences 目录包含每个 Lightning 的文件夹 组织中的社区。请参阅 Experience Cloud 开发人员指南 详。

文件

文档必须位于其父级的目录中 文档文件夹。父文档文件夹必须位于名为 documents 的目录中。每个文档都有相应的元数据 XML 可以使用 XML 编辑器查看的文件。

自定义标签

所有自定义标签都包含在一个名为 <package 的文件中,该文件位于 package 下名为 labels 的目录中 目录>目录。每个包目录都可以 有自己的文件。CustomLabels.labels-meta.xmlCustomLabels.labels-meta.xml

如何在同步时排除源

在本地文件系统和目标组织之间同步元数据时,您通常会有 要排除的源文件。同样,您经常希望在以下情况下排除某些文件 将源转换为 Salesforce DX 源格式。在这两种情况下,您都可以排除个人 文件或特定目录中带有文件的所有文件。

.forceignore

该文件在运行时排除大多数文件 的命令,例如 、 、 和 。.forceignoreprojectproject deploy startproject retrieve startproject convert sourceproject delete source

.forceignore 文件的结构

文件结构模仿该结构。中的每一行都指定一个模式,该模式对应于一个或 更多文件。这些文件通常表示元数据组件,但也可以是所需的任何文件 排除,例如 LWC 配置 JSON 文件或测试。.forceignore.gitignore.forceignore

这些命令在分析文件时,使用与文件相同的规则和模式。这些规则的几个常见示例 模式包括:project.forceignore.gitignore

  • 始终使用正斜杠 () 作为目录 分隔符,即使在使用反斜杠的操作系统(如 Microsoft Windows)上也是如此。/
  • 星号 () 匹配除 forward 以外的任何内容 斜杠 ()。*/
  • 模式中两个连续的星号 () 有 特殊含义,具体取决于它们在路径名中的位置。有关示例,请参阅。**
  • 为了便于阅读,请在文件中使用空行作为分隔符。.forceignore

还有更多的规则和模式。查看 git 文档了解详细信息。

确定元数据组件的确切文件名

在构建文件时,有时 需要要排除的元数据组件的确切名称。最简单的方法 确定特定组件的名称是要查看包目录 包含源文件,例如默认目录。.forceignoreforce-app

例如,配置文件元数据组件位于目录中。假设该目录包含 源文件 。指定 命令排除此组件,添加 此条目到您的:main/default/profilesNotUsedProfile.profile-meta.xmlproject.forceignore

**/NotUsedProfile.profile-meta.xml

确定元数据组件确切名称的另一种方法是查看 如果您也使用 source 的命令 跟踪。例如,如果您有本地或远程更改,请运行 or 命令以显示已更改组件的完整路径名。 此输出显示权限集的文件名和路径中的自定义选项卡 “将部署”部分的列:projectproject deploy previewproject retrieve previewDreamhouseSettings

sf project deploy preview

Will Deploy [2] files.
 Type          Fullname   Path                                                                    
 ───────────── ────────── ─────────────────────────────────────────────────────────────────────── 
 PermissionSet dreamhouse force-app/main/default/permissionsets/dreamhouse.permissionset-meta.xml 
 CustomTab     Settings   force-app/main/default/tabs/Settings.tab-meta.xml

源命令忽略的其他文件

源命令会忽略这些文件,即使它们不包含在文件中:.forceignore

  • 任何以“点”开头的源文件或目录,例如 .DS_Store 或 .sf
  • 任何以 .dup 结尾的文件
  • package2-descriptor.json
  • package2-manifest.json文件

排除尚未与本地源同步的远程更改

有时,您直接在组织中进行更改,但您不想将该更改拉入 您当地的 DX 项目。若要排除远程元数据更改,请向其添加一个条目,该条目表示 如果您确实检索了它,则会创建它。.forceignore

例如,如果您有一个名为 add this entry to 的权限集:Dreamhouse,.forceignore

**/Dreamhouse.permissionset-meta.xml

排除 MetadataWithContent 类型

包含内容的元数据组件(如 ApexClass 或 EmailTemplate)扩展了 MetadataWithContent 类型。这些组件有两个 源文件:一个用于内容本身,例如 Apex 代码或电子邮件模板,以及 随附的元数据文件。例如,HelloWorld Apex 类的源文件是 和 。HelloWorld.clsHelloWorld.cls-meta.xml若要排除 MetadataWithContent 组件(如 ApexClass),请同时列出两个源 文件,或使用星号。为 例:

.forceignore

# Explicilty list the HelloWorld source files to be excluded
helloWorld/main/default/classes/HelloWorld.cls
helloWorld/main/default/classes/HelloWorld.cls-meta.xml

# Exclude the HelloWorld Apex class using an asterisk
helloWorld/main/default/classes/HelloWorld.cls*

排除捆绑包和文件组

使用两个连续的星号 () 忽略文件 分布在多个目录中,只有一个条目。**.forceignore

例如,要排除与名为 的 Lightning Web 组件相关的所有资源文件,请添加此条目以排除整个 组件包:myLwcComponent

**/lwc/myLwcComponent

要排除所有 Apex 类,请执行以下操作:

**/classes

包含特殊字符的元数据

如果元数据名称包含特殊字符(例如正斜杠、反斜杠或 引号),我们将本地文件系统上的文件名编码为所有操作 系统。例如,如果您检索名为 Custom: Marketing Profile 的自定义配置文件,则 冒号在生成的文件名中编码。

自定义%3A 营销配置文件.profile-meta.xml

如果在 .forceignore 中引用带有特殊字符的文件名, 使用编码的文件名。

将 .forceignore 放在哪里

确保您指定的路径是 相对于包含文件的目录。为了让文件发挥其魔力,您 必须将其放在正确的位置,具体取决于您正在运行的命令。.forceignore.forceignore.forceignore

  • 将文件添加到 源跟踪项目 命令。.forceignoreproject
  • 将文件添加到 的元数据检索目录(使用 )中。package.xmlproject convert mdapi

示例语法

以下是一些用于指示要排除的来源的选项。在此示例中,所有路径 相对于项目根目录。

# Specify a relative path to a directory from the project root
helloWorld/main/default/classes

# Specify a wildcard directory - any directory named “classes” is excluded
**classes

# Specify file extensions
**.cls*
**.pdf

# Specify a specific file
helloWorld/main/default/HelloWorld.cls*

列出当前被忽略的文件和目录

使用命令列出文件 以及命令当前忽略的项目中的目录。该命令引用文件以确定忽略的文件列表。project list ignoredprojectproject list ignored.forceignore

若要列出所有包目录中被忽略的所有文件,请运行命令而不 任何标志。使用标志限制检查 复制到特定文件或目录。如果指定目录,该命令将检查所有 子目录递归。–source-dir

此示例检查是否忽略了特定文件。

sf project list ignored --source-dir package.xml

此示例获取特定目录中所有被忽略文件的列表。

sf project list ignored --source-dir force-app/main/default

命令找到被忽略的文件时的示例输出:

Found the following ignored files:
force-app/main/default/aura/.eslintrc.json
force-app/main/default/lwc/.eslintrc.json
force-app/main/default/lwc/jsconfig.json

未忽略文件时的示例输出:

No ignored files found in paths:
README.md

从现有源创建 Salesforce DX 项目

如果您是 Salesforce 开发人员、合作伙伴或 ISV,您可能在 打包组织中的托管包或沙盒或生产组织中的应用程序源。 在开始使用 Salesforce DX 之前,请将现有源检索到 Salesforce DX 中 项目。

  1. 创建 Salesforce DX 项目。sf project generate --name MyProject
  2. 切换到项目目录。cd MyProject
  3. 通过运行项目检索来检索源 start 命令。当前源的位置和格式决定了命令 必须使用的标志。当前源的格式和位置用于检索源的命令你是合作伙伴,已将源定义为托管包,而 包装组织。sf project retrieve start --package-name <package-name> --target-org <sourceOrg-username-or-alias>该标志指定用户名或 要从中检索源的源组织(例如打包组织)的别名。 该标志指定包名称;如果 名称包含一个空格,用双引号括起来。–target-org–package-name默认情况下,该命令会创建一个包目录,其名称与包相同。 在 DX 项目目录中。然后,该命令从包中检索源,然后 使用标准的 DX 源格式结构将其组织在新目录中。使用 指定其他目录;这 命令创建该目录(如果该目录不存在)。–output-dir您有一个清单文件,通常称为 package.xml,它 在沙盒或生产组织中定义未打包的源。sf project retrieve start --manifest <manifest-file> --target-org <sourceOrg-username-or-alias>该标志指定用户名或 要从中检索的组织(例如沙盒或生产)的别名 源。该标志指示 清单文件,通常称为 .–target-org–manifestpackage.xml默认情况下,该命令将源代码检索到 DX 项目的现有包目录中 使用 指定不同的目录;这 命令创建该目录(如果该目录不存在)。force-app–output-dir提示如果您已经有一个存储库,该存储库遵循从 元数据 API 检索,则存储库中的源文件采用元数据格式。您可以 将这些文件转换为源格式,并将它们包含在您的 Salesforce DX 项目中。有关详细信息,请参阅将元数据格式的文件转换为源格式。
  4. 如果检索在项目中创建了包目录,请将其添加到 sfdx-project.json 文件中。

您是否在沙盒或生产组织中有源代码,但没有清单文件 (package.xml)将其检索到您的项目?使用 CLI 命令创建一个。例如 此命令从组织中的元数据组件生成别名为 的清单。

project generate manifestprod-org

sf project generate manifest --from-org prod-org

看 命令帮助以获取更多示例和 信息。

sf project generate manifest --help

你 也可以参考元数据中的示例包 .xml 清单文件 API 开发人员指南。

将元数据格式的文件转换为源格式

如果您已经有一个存储库,其中您已使用 元数据 API,文件为元数据格式。您可以将这些文件转换为源文件 格式化并将它们添加到您的 Salesforce DX 项目中。然后,您可以将它们部署并检索到 和 使用 CLI 命令从您的组织,并使用源跟踪来跟踪更改。

convert 命令将忽略所有以“点”开头的文件,例如 .DS_Store。若要从转换过程中排除更多文件,请添加 .forceignore 文件。

  1. 切换到您的 Salesforce DX 项目目录。
  2. 使用 project convert mdapi 命令将文件从元数据格式转换为源格式。假设您的元数据格式 文件位于名为 /Users/testing/mdapi_project 的目录中。sf project convert mdapi --root-dir /Users/testing/mdapi_project标志是目录的名称 包含元数据格式文件。–root-dir转换后的源代码存储在 sfdx-project.json 文件中指示的默认包目录中,通常命名为 。使用标志将转换后的文件放在不同的包目录中;这 命令创建该目录(如果该目录不存在)。force-app–output-dir
  3. 如果转换在项目中创建了包目录,请将其添加到 sfdx-project.json 文件中。

Salesforce DX 用户名和组织

许多 Salesforce CLI 命令连接到组织以完成其任务。例如,创建临时组织的命令, 连接到 Dev Hub 组织。和命令同步源代码 在您的项目和组织之间。在每种情况下,CLI 命令都需要用户名来确定 要连接到哪个组织。用户名在整个 Salesforce 生态系统中是唯一的,并且是 仅与一个组织关联。

org create scratchproject deploy startproject retrieve start

创建临时组织时,CLI 会生成一个用户名。用户名看起来像一封电子邮件 地址,例如 test-wvkpnfm5z113@example.com。您不需要密码即可连接到或 打开一个临时组织,但您可以稍后使用该命令生成一个组织。org generate password

Salesforce 建议您将在开发期间最常连接到的组织设置为 您的默认组织。最简单的设置方法是登录到 Dev Hub 组织或创建 划痕组织;您还可以使用 config 命令。分别指定 or 标志。您还可以创建一个别名,使组织的 用户名更具可读性和直观性。您可以互换使用用户名或其别名 用于连接到组织的所有 CLI 命令。–set-default-dev-hub–set-default

这些示例在您登录并授权组织时设置默认组织和别名,在此 案例为 Dev Hub 组织,然后在创建临时组织时。

sf org login web --set-default-dev-hub --alias my-hub-org
sf org create scratch --definition-file config/project-scratch-def.json --set-default --alias my-scratch-org

要验证 CLI 命令是否需要组织连接,请查看带有标志的标志列表。具有该标志的命令连接到开发人员中心组织。同样地 已连接到临时组织的命令, 沙箱等。本示例显示有关 的标志列表和帮助信息。-h–target-dev-hub–target-orgorg create scratch

sf org create scratch -h

当您运行需要组织连接且未指定用户名的 CLI 命令时, 该命令使用默认值。若要显示已授权或创建的所有组织,请运行组织列表。默认的 Dev Hub 和临时组织 左侧标有表情符号;请参阅显示屏末尾的图例 详。

让我们来看看几个例子。此示例将源代码部署到您设置的组织 作为默认值。

sf project deploy start

要指定缺省组织以外的组织,请使用 。例如,假设您创建了一个别名为 的临时组织。这不是默认的,而是你 仍然想将源部署到它。–target-orgmy-other-scratch-org

sf project deploy start --target-org my-other-scratch-org

此示例演示如何使用标志 以在创建临时组织时指定非默认的 Dev Hub 组织。–target-dev-hub

sf org create scratch --target-dev-hub jdoe@mydevhub.com --definition-file my-org-def.json --alias yet-another-scratch-org

有关设置默认组织的详细信息

如果您已经创建了临时组织,则可以将其或任何其他组织设置为默认组织 通过从项目运行命令 目录。config set

sf config set target-org test-wvkpnfm5z113@example.com

该命令在本地设置值,因此它仅适用于当前项目。要使用 默认组织 对于计算机上的所有项目,请指定标志。您可以从任何目录运行此命令。本地项目 默认值覆盖全局默认值。–global

sf config set target-org test-wvkpnfm5z113@example.com --global

该过程类似于设置默认的 Dev Hub 组织,只是你使用 config 变量。target-dev-hub

sf config set target-dev-hub jdoe@mydevhub.com

要取消设置配置变量,请运行以下命令。使用该标志为所有人取消设置 您的 Salesforce DX 项目。config unset–global

sf config unset target-org --global

要查看您设置的所有配置变量,请运行 ;如果从项目目录运行它,它还会列出本地目录。config list

sf config list

有关锯齿的更多信息

使用该命令为 您已经创建的临时组织,或您授权后的任何组织。您可以创建一个 任何组织的别名:Dev Hub、临时组织、生产、沙盒等。因此,当您发出 命令需要组织的用户名,使用易于记忆的别名可以加快速度。alias set

sf alias set my-scratch-org test-wvkpnfm5z113@example.com

别名还使设置默认组织变得容易。当您使用别名而不是 实际用户名。config settarget-org

sf config set target-org my-scratch-org

通过用空格分隔名称-值对,使用单个命令设置多个别名; 在这种情况下,您必须使用等号。

sf alias set org1=<username> org2=<username>

一次只能将一个别名与一个用户名关联。如果多次设置, 别名指向最新的用户名。例如,如果运行以下两个 命令,别名 my-org 设置为 test-wvkpnfm5z113@example.com。

sf alias set my-org test-blahdiblah@example.com
sf alias set my-org test-wvkpnfm5z113@example.com

若要查看已设置的所有别名,请使用以下命令之一。

sf alias list
sf org list

要删除别名,请使用以下命令。alias unset

sf alias unset my-org

列出您的所有组织

使用命令显示用户名和 您已授权的组织和您创建的活动临时组织的别名。org list

sf org list

    Type    Alias          Username                                      Org ID             Status                Expires
 ── ─────── ────────────── ───────────────────────────────────────────── ────────────────── ───────────────────── ──────────
 D DevHub  JulesDevHub    jules@sf.com                                  00DB0001234c7jiMAA Connected 
   Sandbox                jules@sf.com.jssandtwo                        00D020012344XTiEAM Connected
 O Scratch my-scratch-org test-qjrr9q5d13o8@example.com                 00DMN0012342Gez2AE Active                2023-08-21    

Legend:  D=Default DevHub, O=Default Org      Use --all to see expired and deleted scratch orgs

输出列出了已授权或创建的组织,包括开发人员中心组织、 生产组织、临时组织和沙盒。该表显示您的用户名 指定了您何时授权组织、其别名、其 ID 以及 CLI 是否可以 连接到它。左侧的表情符号指向默认组织或 Dev Hub;请参阅 图例在底部了解详情。临时组织还会显示其到期日期。

要查看更多信息,例如临时组织创建日期和关联的 DevHub 组织, 和所有组织的实例 URL,请使用该标志。–verbose

sf org list --verbose

使用该标志删除非活动暂存组织 从列表中。该命令在执行任何操作之前会提示您。–clean

sf org list --clean

将命名空间链接到 Dev Hub 组织

要将命名空间与临时组织一起使用,必须链接 Developer Edition 组织,其中 命名空间已注册到 Dev Hub 组织。

在链接命名空间之前,请完成这些任务。

  • 如果您没有具有已注册命名空间的组织,请创建一个 Developer Edition 组织,该组织是 独立于 Dev Hub 或临时组织。如果您已经有一个组织,并且注册了 命名空间,你就可以开始了。
  • 在 Developer Edition 组织中,创建并注册命名空间。重要请仔细选择命名空间。如果您正在试用此功能或需要 出于测试目的,请选择一次性命名空间。不要选择要使用的命名空间 将来用于生产组织或其他一些实际用例。关联 命名空间,则无法更改或重用它。
  1. 以系统管理员或 Salesforce DX 用户身份登录 Dev Hub 组织 命名空间注册表权限。提示确保浏览器允许来自开发人员中心组织的弹出窗口。
    1. 从“应用程序启动器”菜单中,选择“命名空间注册表”。
    2. 单击“链接命名空间”。
  2. 在弹出的窗口中,登录到您的命名空间所在的 Developer Edition 组织 使用组织的系统管理员凭据进行注册。您无法链接没有命名空间的组织:沙箱、临时组织、补丁组织和分支 组织需要将命名空间链接到命名空间注册表。

若要查看链接到命名空间注册表的所有命名空间,请选择“全部” 命名空间注册表列表视图。

Salesforce DX 项目配置

项目配置文件 sfdx-project.json 指示该目录是 Salesforce DX 项目。配置文件包含项目 信息,并促进组织的授权和第二代的创建 包。它还告诉 Salesforce CLI 在项目和 组织。

我们在 使用 Salesforce CLI 或 Salesforce Extensions for VS Code 创建项目的示例存储库。

注意

是否打算创建第二代软件包?准备就绪后,添加 特定于打包的配置选项,用于支持包创建。请参阅项目配置文件以获取 第二代托管软件包。

我们建议您使用源签入此文件。

{ 
"packageDirectories" : [ 
    { "path": "force-app", "default": true}, 
    { "path" : "unpackaged" }, 
    { "path" : "utils" } 
  ],
"namespace": "", 
"sfdcLoginUrl" : "https://login.salesforce.com", 
"sourceApiVersion": "58.0"
}

您可以手动编辑这些参数。名称(Salesforce Functions 需要)

Salesforce DX 或 Salesforce Functions 项目名称。namespace(可选)

与包一起使用的全局命名空间。命名空间必须注册到 与开发人员中心组织关联的组织。此命名空间分配给暂存 使用该命令创建的组织。 如果要创建未锁定的包,则可以选择创建没有 命名空间。org create scratch

重要

向 Salesforce 注册命名空间,然后连接组织 替换为已注册的命名空间到 Dev Hub 组织。oauthLocalPort(可选)默认情况下,OAuth 端口为 1717。如果 1717 已在使用中,并且您 计划在开发人员中心组织中创建连接的应用,以支持基于 JWT 的授权。是 确保还按照在组织中创建连接的应用程序中的步骤更改回调 网址。packageAliases(可选)

程序包 ID 的别名,通常可能很隐晦。请参阅项目配置文件以获取 第二代托管包了解详细信息。packageDirectories (必需)

包目录指示将源同步到和 来自组织。这些目录可以包含来自托管或非托管的源文件 包。它们还可以包含由蚂蚁生成的未打包源文件 工具或更改集。有关所有选项的信息,请参阅 项目配置文件 第二代托管软件包。packageDirectories

使用包目录时,请记住这些事项。

  • 包目录的位置是相对于项目的位置。不要指定 绝对路径。以下两个示例是等效的。"path": "helloWorld" "path" : "./helloWorld"
  • 只能有一个默认路径(包目录)。如果只有一条路径, 我们假设它是默认值,因此您不必显式设置参数。如果有多个路径,则必须 指示哪一个是默认值。default
  • Salesforce CLI 在以下情况下使用默认包目录作为目标目录 从组织检索到本地项目的更改。也使用此默认路径 创建第二代软件包时。
  • 如果未指定输出目录,则默认包目录也是 在源转换期间存储文件的位置。源转换均来自 元数据格式到源格式,以及从源格式到元数据格式。

plugins(可选)

要使用您创建的自定义插件,请使用 Salesforce DX 项目,请向 sfdx-project.json 文件添加一个部分。在本节中,添加配置值 和设置来更改插件的行为。plugins

"plugins": {
  "yourPluginName": {
    "timeOutValue": "2"
  },
  "yourOtherPluginName": {
    "yourCustomProperty": true
  }
}

仅存储要签入到源的值的配置变量 对项目的控制。这些配置值会影响整个开发 团队。pushPackageDirectoriesSequentially (可选) (已弃用)

注意

此属性已弃用,仅适用于不推荐使用的命令。它不会影响行为 的命令。部署 按特定顺序打包,按所需顺序使用单独的命令。force:source:pushproject deploy startproject deploy start设置为推送多个包目录 按照使用 时列出的顺序排列。这些目录是 推送单独的事务。此属性的默认值为 ,这意味着多个包目录是 部署在单个事务中,不考虑顺序。例:

truepackageDirectoriesforce:source:pushfalse

"packageDirectories": [
    {
      "path": "es-base-custom",
      "default": true
    },
    {
      "path": "es-base-ext"
    }
  ],
  "pushPackageDirectoriesSequentially": true,

更换件(可选)

自动将元数据源文件中的字符串替换为特定值 在将文件部署到组织之前。

请参阅之前替换代码中的字符串 部署了解详细信息。sfdcLoginUrl(可选)

命令使用的登录 URL。如果 未指定,默认值为 https://login.salesforce.com。如果需要用户,请覆盖默认值 授权给特定的 Salesforce 实例。例如,如果要授权 进入沙盒组织,将此参数设置为 。org loginhttps://test.salesforce.com

如果未在此处指定默认登录 URL,或者在项目外部运行,请指定实例 URL 使用标志授权组织时。org login–instance-urlsourceApiVersion(可选)

源兼容的 API 版本。默认值为与 Salesforce CLI。

该值确定字段 在 、 或 期间为每种元数据类型检索。如果您使用 在最新版本中已更改的元数据类型。您需要指定版本 的元数据源。例如,假设向 CustomTab 添加了一个新字段 适用于 API 版本 58.0。如果检索版本 57.0 或更早版本的组件,则会看到 运行命令时出错,因为 组件不包含该字段。sourceApiVersionproject deployproject retrieveproject convertproject

不要将此项目配置参数与 org-api-version CLI 混淆 配置变量,该变量具有相似的名称。请参阅 API 版本和源 API 版本的工作原理 Salesforce CLI 了解更多信息。

多个包目录

创建 Salesforce DX 项目时,我们建议您组织元数据 通过在本地创建多个包目录,将其组合到逻辑分组中。然后定义这些 文件中的目录。您可以分组 应用程序或自定义项的类似代码和源代码,以更好地组织团队的 存储 库。稍后,如果您决定使用第二代软件包 (2GP),则这些目录 对应实际的 2GP 包。

sfdx-project.json

注意

为清楚起见,包目录是指包含 分解的元数据文件,即源格式的元数据。此目录并不总是 结果为 2GP 包。封装是指 2GP 封装。

在文件中,列出每个包 目录。 每个本地包目录都遵循标准的 Salesforce DX 项目结构。sfdx-project.jsonpackageDirectories

多包目录结构仅是客户端(本地)的。当您部署 源到组织,没有 其本地包目录位置与组织中的包之间的关联。你 通过显式安装 2GP封装。project deploy start

部署、检索和 转换元数据支持多个包目录。project

如何设置?

设置多个包目录很容易。 如何在这些目录中组织本地源代码需要更多的思考和 规划,并取决于您的开发环境。计划如何组织代码 你开始吧。随着项目的发展,保持源代码井井有条 让您的开发人员更轻松、更高效地工作。

假设你把 默认包目录中自定义对象 MyObject 的分解元数据文件。你 然后,可以将 MyObject 上的新字段 MyField 的文件放在不同的“扩展”包中 目录中,而不必同时包含 MyObject 文件。虽然这很简单 例如,您可以采用任意数量的不同方式组织代码。这些博客文章提供了一些想法。

这是 如何设置多个包目录。让我们先看一个示例片段:sfdx-project.json

"packageDirectories": [
    {
      "path": "es-base-custom",
      "default": true
    },
    {
      "path": "es-base-ext"
    },
    {
      "path": "es-base-styles"
    }
  ],

示例代码段定义了三个 软件包目录:(缺省值)、和 。假设您的顶级本地项目目录称为 。下面的目录层次结构 它看起来像这样:sfdx-project.jsones-base-customes-base-extes-base-styleseasy-spaces-lwc

每个目录都符合标准 Salesforce DX 项目结构。例如,该目录如下所示:es-base-*es-base-ext

现在,将分解的元数据源添加到这些多个包目录中 最适合您的开发环境。

它是如何工作的?

让我们通过几个例子来了解如何使用 多个包目录。project deploy startproject retrieve start

对于新组织,命令 在文件中列出的所有多个包目录中部署所有元数据。之后,该命令仅部署 新建、更改或标记为删除的元数据。默认情况下,该命令将部署 单个事务中的元数据,就好像您只有一个包目录一样。default project deploy startsfdx-project.json

sf project deploy start --target-org my-org

还可以将要部署的元数据作为目标。可以部署特定包 目录、特定元数据组件、清单文件中列出的组件等。 此示例在包目录中部署元数据:es-base-custom

sf project deploy start --source-dir es-base-custom --target-org my-org

此示例部署在所有多个包目录中找到的所有 Apex 类:

sf project deploy start --metadata ApexClass --target-org my-org

运行 时,命令 将组织中的所有远程更改检索到本地项目中。对于每个检索到的 组件,该命令将在所有软件包目录中查找本地匹配项。如果它发现一个 match,命令会更新它。如果找不到匹配项,该命令将复制本地 组件添加到默认包目录中,在我们的示例中是 .project retrieve startes-base-custom

sf project retrieve start --target-org my-org

然后,您可以将检索到的文件移动到对您有意义的包目录中 项目。使用 将移动的文件部署回组织后,Salesforce CLI 会跟踪其新位置。project deploy start

您还可以用于检索 来自组织的目标元数据。现有元数据将检索到其正确的本地 package 目录和新的元数据放入默认的 package 目录。这个例子 仅检索本地包目录中包含的元数据组件:project retrieve startes-base-custom

sf project retrieve start --source-dir es-base-custom  --target-org my-org

此示例从您的组织中检索所有 Apex 类;新类进入默认值 包目录和本地存在的类进入其对应的包中 目录。

sf project retrieve start --metadata ApexClass --target-org my-org

按顺序推送源

默认情况下,将元数据部署到 您的组织在单个事务中,无论您列出多个事务的顺序如何 中的包目录。但有时 您必须指定推送包目录的确切顺序。原因 包括:project deploy startsfdx-project.json

  • 本地项目中重构的元数据组件文件的数量超过 Salesforce 元数据限制为每次检索或部署 10,000 个文件。一种解决方法是 将元数据拆分为多个包目录,每个目录包含的量小于此值 按顺序限制和推送每个目录,从而单独限制和推送。
  • 多个包目录之间存在依赖关系,这要求它们 按特定顺序推送。
  • 多个包目录包含相同的元数据组件,并且您希望 指定最后部署的那个,这样它就不会被覆盖。

如果需要按特定顺序进行多个部署,请使用 or 标志在 所需的顺序。project deploy start–source-dir–metadata

在部署之前替换代码中的字符串

自动将元数据源文件中的字符串替换为特定值 在将文件部署到组织之前。

以下示例用例描述了使用部署前字符串替换的方案:

  • NamedCredential 包含用于测试的终结点。但是当你部署 source 添加到您的生产组织,您需要指定不同的终端节点。
  • ExternalDataSource 包含您不想存储在存储库中的密码。 但是,您需要将密码与元数据一起部署。
  • 您将几乎相同的代码部署到多个组织。你想有条件地换掉一些 值取决于要部署到的组织。

当源格式的文件转换为 ZIP 文件时,会发生字符串替换 使用命令部署到组织。字符串替换导致的更改永远不会写入您的项目; 它们仅适用于已部署的文件。project deploy start

配置字符串替换

通过向文件添加属性来配置字符串替换。该物业 接受多个条目,这些条目由定义以下项的键组成:replacementssfdx-project.json

  • 包含要替换的字符串的源文件。
  • 要替换的字符串。
  • 替换值。

让我们看一个例子,看看它是如何工作的;请参阅本主题后面的更多示例。这 sample 指定当文件 deployed,则字符串的所有匹配项都是 替换为THE_REPLACEMENT环境的值 变量:

sfdx-project.jsonforce-app/main/default/classes/myClass.clsreplaceMe

{
  "packageDirectories": [
     {
       "path": "force-app",
       "default": true
     }
  ],
  "name": "myproj",
  "replacements": [
    {
      "filename": "force-app/main/default/classes/myClass.cls",
      "stringToReplace": "replaceMe",
      "replaceWithEnv": "THE_REPLACEMENT"  
    }
  ]
}

可以在属性中指定这些键。replacements文件的位置以下属性之一是必需的:

  • filename:包含 要替换的字符串。
  • glob:包含 要替换的字符串。例:。**/classes/*.cls

要替换的字符串以下属性之一是必需的:

  • stringToReplace:要 取代。
  • regexToReplace:正则表达式(正则表达式) 指定要替换的字符串模式。

重置价值以下属性之一是必需的:

  • replaceWithEnv:指定字符串为 替换为指定环境变量的值。
  • replaceWithFile:指定字符串为 替换为指定文件的内容。

条件处理这些属性是可选的:

  • replaceWhenEnv:指定字符串 仅当特定环境变量设置为特定 价值。使用该属性指定 环境变量和属性 指定触发字符串替换的值。envvalue
  • allowUnsetEnvVariable:使用的布尔属性 与属性。当设置为 时,指定如果未设置环境变量,则 在部署之前,从文件中删除替换字符串。换言之, 用什么都没有替换它。当设置为 ( 默认值),如果未设置环境变量,则会出现错误。replaceWithEnvtruereplaceWithEnvfalsereplaceWithEnv

请遵循以下语法规则:

  • 始终对目录使用正斜杠 (), 即使在 Windows 上。/
  • JSON 和正则表达式都使用反斜杠 () 作为转义字符。因此,当您使用正则表达式 匹配一个点,这需要转义,你必须对值使用两个反斜杠:\regexToReplace"regexToReplace" : "\\."同样地 若要匹配单个反斜杠,必须指定其中的三个。"regexToReplace" : "\\\"

例子

此示例与上一个示例类似,但显示了如何 为两个配置字符串替换 文件:

"replacements": [
  {
    "filename": "force-app/main/default/classes/FirstApexClass.cls",
    "stringToReplace": "replaceMe",
    "replaceWithEnv": "THE_REPLACEMENT"
  },
  {
    "filename": "force-app/main/default/classes/SecondApexClass.cls",
    "stringToReplace": "replaceMe",
    "replaceWithEnv": "THE_REPLACEMENT"
  }
]

此示例演示如何指定仅进行字符串替换 如果存在名为 DEPLOY_DESTINATION 的环境变量,并且其值为 。PROD

"replacements": [
  {
    "filename": "force-app/main/default/classes/myClass.cls",
    "stringToReplace": "replaceMe",
    "replaceWithEnv": "THE_REPLACEMENT",
    "replaceWhenEnv": [{
      "env": "DEPLOY_DESTINATION",
      "value": "PROD"
    }]  
  }
]

在此示例中,如果未设置环境变量 SOME_ENV_THAT_CAN_BE_BLANK,则在部署文件时将删除文件中的字符串。如果环境 变量设置为一个值,然后该值将替换字符串。myNS__myClass.clsmyNS__

"replacements": [
    {
      "filename": "/force-app/main/default/classes/myClass.cls",
      "stringToReplace": "myNS__",
      "replaceWithEnv": "SOME_ENV_THAT_CAN_BE_BLANK",
      "allowUnsetEnvVariable": true
    }
  ]

此示例指定,当部署目录中的 Apex 类文件时,所有 字符串的匹配项替换为 文件的内容。force-app/main/defaultreplaceMereplacementFiles/copyright.txt

"replacements": [
  {
    "glob": "force-app/main/default/classes/*.cls",
    "stringToReplace": "replaceMe",
    "replaceWithFile": "replacementFiles/copyright.txt"
  }
]

使用正则表达式指定文本的搜索模式,而不是文本的搜索模式。为 例如,Apex 类 XML 文件始终包含指定 Salesforce API 版本的元素,如 这个片段。

<apiVersion>

<?xml version="1.0" encoding="UTF-8" ?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <status>Active</status>
</ApexClass>

假设您想在最近的 Apex 类上测试您的 Apex 类 API 版本,然后再实际更新所有类。此示例演示如何使用 用于搜索元素的正则表达式。在部署时,该元素将替换为一个特定的字符串,例如 ,该字符串包含在 文件。

<apiVersion><apiVersion>58.0</apiVersion>replacementFiles/latest-api-version.txt

"replacements": [
  {
    "glob": "force-app/main/default/classes/*.xml",
    "regexToReplace": "<apiVersion>\\d+\\.0</apiVersion>",
    "replaceWithFile": "replacementFiles/latest-api-version.txt"
  }
]

测试字符串替换

按照以下步骤测试字符串替换,而无需实际将文件部署到 组织。

  1. 将环境变量设置为 。SF_APPLY_REPLACEMENTS_ON_CONVERTtrue
  2. 运行命令,该命令 将源文件转换为元数据 API 格式。为 例:project convert sourcesf project convert source --output-dir mdapiOut --source-dir force-app
  3. 检查输出目录中的文件(在我们的示例中为字符串替换),以及将部署到 组织。mdapiOut

警告

将密码或机密写入文件系统时要小心,同时 测试。此外,请务必重置您在测试期间设置的任何环境变量,以便它们 以后不会意外应用。

技巧和窍门

  • (仅限 macOS 或 Linux)使用 or 属性时,可以指定 环境变量应用于单个命令,方法是在 命令执行。为 例:replaceWithEnvreplaceWhenEnvTHE_REPLACEMENT="some text" DEPLOY_DESTINATION=PROD sf project deploy start警告以这种方式设置密码或密码时要小心,因为它们会显示 在您的终端历史记录中。
  • 如果您配置了许多字符串替换,并且发现它难以管理, 查看开源工具,这些工具将一个或多个文件的内容加载到 环境,例如 dotenv-cli。在此示例中,环境变量在 在命令执行之前加载两个本地文件:.envproject deploy startdotenv -e .env1 -e .env2 sf project deploy start警告不要在文件中提交密码或机密。.env
  • 如果指定 ,则 JSON 输出将包含一个属性,该属性列出了受影响的文件和 已替换的字符串。如果指定 and ,则 JSON 输出不包括该属性。–jsonproject deploy startreplacements–json–concisereplacements查看字符串 替换信息,请指定 。project deploy start–verbose

注意事项和限制

  • 如果在多个文件中配置多个字符串替换,则 部署可能会降级。如果可能,请考虑使用密钥,以确保只打开一个文件。如果必须使用 ,请尝试限制 打开的文件数 指定单个目录或元数据类型。filenameglob例如,目标 特定目录中的 Apex 类文件,这比 搜索所有 Apex 的 要好。 所有包目录中的元数据文件。“glob”: “force-app/main/default/classes/*.cls”“glob”: “**/classes/**”
  • 在静态资源中使用字符串替换时要小心。不做字符串时 替换,Salesforce CLI 在第一次遇到时只是压缩所有静态资源 他们的目录并按原样部署它们。如果为大 静态资源目录,CLI 必须检查比平时多得多的文件,这可以 降低性能。
  • 在以元数据格式进行部署时,不能使用字符串替换,例如使用 命令。project deploy start –metadata-dir
  • 如果部署超时,或者您指定了 的标志 和 然后运行或查看发生了什么,部署 文件像往常一样包含字符串替换。但是,和的输出不会显示与应有的字符串替换信息相同的字符串替换信息。–asyncproject deploy startproject deploy resumeproject deploy reportproject deploy resumeproject deploy reportproject deploy start –verbose

将 Experience Cloud 站点从沙盒部署到生产环境

我们建议在测试中创建、自定义和测试您的 Experience Cloud 站点 环境,例如沙盒,然后再将其部署到生产组织。当测试是 完成时,您可以使用更改集或元数据 API 将站点从一个组织迁移到另一个组织。 决定是使用变更集还是 MD API 取决于几个因素。需要考虑的一些事项 是要迁移的更改的复杂性,还是您对开发人员的满意程度 工具,以及您正在使用的应用程序生命周期管理 (ALM) 模型。

提示

要了解有关可用的 ALM 模型和开发选项的更多信息,请执行以下操作: 查看确定哪个应用程序生命周期 管理模式非常适合您在 Trailhead 上。

注意

Lightning Bolt 解决方案不适合在 组织。使用 Lightning Bolt 解决方案在 AppExchange 上共享或销售解决方案,或实施 具有交钥匙解决方案或新外观的网站。

更改集

如果您更习惯使用点击式工具,那么更改集就是您的部署 朋友。更改集表示组织(或元数据组件)中的一组自定义项 您可以部署到连接的组织。

您可以使用声明性工具管理应用程序。您不必使用命令行 接口或版本控制系统,以满足您的定制需求。您可以使用“设置”菜单 在开发环境中创建更改。然后,将更改迁移到 环境,在您完成 ALM 步骤时。

发布工件是一组相对于生产组织中的内容的元数据更改。 发布的只是已添加或更改的元数据,如果它没有更改,则它是 不在版本中。

元数据 API

如果您能够快速掌握元数据 API,并且对代码世界更熟悉,请使用元数据 用于以编程方式部署更改的 API。您可以检索、部署、创建、更新和删除 组织的自定义信息,例如 Experience Cloud 站点、自定义对象 定义和页面布局。

当您的更改很复杂或需要更严格的更改时,使用元数据 API 是理想的选择 变更管理流程和审计流程(或版本控制系统)来管理多个 工作流。

与更改集过程一样,您创建的发布工件是一组元数据 相对于生产组织的变化。

提示

某些 Experience Cloud 站点设置和功能尚不受支持 元数据 API,因此您必须在环境之间手动迁移它们。请记住跟踪这些 更改,以便您不会忘记迁移它们。

  • 使用更改集
    部署 Experience Cloud 站点 使用更改集在具有部署连接的相关组织之间移动全部或部分 Experience Cloud 站点。您可以使用网络组件类型移动任何完整的 Experience Cloud 站点。或者,您可以使用“数字体验”组件类型移动增强型 LWR 站点的部分站点内容。
  • 使用元数据 API 部署 Experience Cloud 站点 使用元数据 API
    将 Experience Cloud 站点从一个 Salesforce 组织移动到另一个组织。在测试环境中设置和测试站点,然后检索站点的数据并将其部署到生产组织。
  • Experience Builder 站点的 ExperienceBundle ExperienceBundle 元数据类型提供构成 Experience Builder 站点
    的不同设置和组件(如页面、品牌集和主题)的基于文本的表示形式。无论是您自己的组织,还是咨询合作伙伴或 ISV,您都可以使用首选开发工具(包括 Salesforce Extensions for VS Code、Salesforce CLI 或您喜欢的 IDE 或文本编辑器)以编程方式快速更新和部署站点。
  • 从24年冬季开始,在迁移到增强型LWR站点时避免部署问题,您无法再禁用23年冬季首次引入的增强型站点
    和内容平台。因此,默认情况下,从 LWR 模板创建的任何站点现在都是增强的 LWR 站点。与使用 ExperienceBundle 元数据类型的非增强型 LWR 站点不同,增强型 LWR 站点使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。但是,如果您在 24 年冬季之前在源组织(如沙盒)上创建了非增强型 LWR 站点,并且现在希望首次将该站点部署到目标组织(如生产),则元数据类型的这种差异可能会导致部署问题。
  • 部署经过身份验证的 LWR 站点
    的注意事项 从 23 年冬季开始,通过 Experience Builder 或 Connect API 创建的新 LWR 站点在其 URL 末尾不包含 /s。在 23 年冬季之前创建的经过身份验证的 LWR 站点的 URL 仍包含 /s,如果沙盒和生产 URL 不匹配,则此 URL 结构更新会影响部署。了解支持哪些部署方案,以及如何解决与 /s 相关的不受支持的部署错误。

使用更改集部署 Experience Cloud 站点

使用更改集在相关组织之间移动全部或部分 Experience Cloud 站点 具有部署连接。您可以使用 Network 组件类型来移动任何完整的 Experience Cloud 站点。或者,您可以使用“数字体验”组件类型移动部分站点 增强型 LWR 站点的内容。

  • 使用更改集
    部署完整的 Experience Cloud 站点 使用更改集在具有部署连接的相关组织(例如沙盒和生产组织)之间移动 Experience Cloud 站点。在测试环境中创建、自定义和测试站点,然后在测试完成后将站点迁移到生产环境。
  • 使用更改集
    部署部分 Experience Cloud 站点内容 使用更改集在具有部署连接的相关组织(例如沙盒和生产组织)之间移动各个 Experience Cloud 组件和内容。在测试环境中创建和测试更改,然后在准备就绪时仅将这些更改迁移到生产环境。
  • 部署具有更改集
    的 Experience Cloud 站点的注意事项 在迁移具有更改集的 Experience Builder 或 Salesforce 选项卡 + Visualforce 站点时,请记住以下注意事项和限制。

使用更改集部署完整的 Experience Cloud 站点

使用更改集在具有 部署连接,例如沙盒和生产组织。创建、自定义和测试 测试环境中的站点,然后在测试时将站点迁移到生产环境 完成。

用户权限 需要
要自定义或发布 Experience Cloud 站点,请执行以下操作:创建和设置体验
若要编辑部署连接并使用入站更改集,请执行以下操作:部署更改集并修改所有数据注意如果用户 仅需要访问部署的元数据,则可以启用修改 元数据:通过元数据 API 函数权限。此权限提供以下 用户部署所需的访问权限,而无需提供对组织数据的访问权限。 有关详细信息,请参阅《通过元数据 API 函数权限修改元数据》中的 “修改元数据” Salesforce 帮助。
要使用出站更改集,请执行以下操作:创建和上载更改集,创建 AppExchange 软件包,并上传 AppExchange 软件包

您可以使用更改集来移动完整的 Experience Builder 和 Salesforce 选项卡 + Visualforce 使用网络组件类型的站点。

  1. 在首选测试组织(如沙盒)中创建和测试站点。
  2. 在测试组织的“设置”中,在 “快速查找”框,然后选择“出站更改集”。
  3. 创建更改集,然后单击“更改集组件”中的“添加” 部分。
  4. 选择“网络”组件类型,选择您的站点,然后选择 单击添加到更改集
  5. 若要添加依赖项,请单击“查看/添加依赖项”。我们 建议选择列出的所有依赖项。提示
    • 对于链接到标准对象的导航菜单,自定义列表视图不是 作为依赖项包含在内。手动将自定义列表视图添加到更改中 列表。
    • 手动添加“管理”|”成员
    • 依赖项列表有两个 Site.com items— 和 . 保存您可以设置的各种 Visualforce 页面 在 Experience Workspaces 的管理中。 包括 Experience Builder 中的页面。MySiteNameMySiteName1MySiteNameMySiteName1
  6. 单击“上传”,然后选择您的目标组织,例如 生产。确保目标组织允许入站连接。入站和出站 组织必须具有部署连接。
  7. 从“设置”中,选择“入站更改集”并查找更改集 您从源组织上传的。
  8. 验证并部署更改集,使其在目标组织中可用。警告当您部署入站更改集时,它会覆盖 目标组织。
  9. 手动重新配置目标组织站点中任何不受支持的项目。
  10. 为您的网站添加数据,并对其进行测试以确保一切按预期工作。 然后发布您的更改以上线。

使用更改集部署部分 Experience Cloud 站点内容

使用更改集在 具有部署连接的相关组织,例如沙盒和生产组织。创造 并在测试环境中测试更改,然后在以下情况下仅将这些更改迁移到生产环境 他们已经准备好了。

所需的用户权限
要自定义或发布 Experience Cloud 站点,请执行以下操作:创建和设置体验
若要编辑部署连接并使用入站更改集,请执行以下操作:部署更改集并修改所有数据注意如果用户只需要访问元数据 对于部署,您可以启用通过元数据修改元数据 API 函数 许可。此权限为此类用户提供了部署所需的访问权限,而无需 提供对组织数据的访问。有关详细信息,请参阅“通过元数据 API 修改元数据 Salesforce 帮助中的“Functions 权限”。
要使用出站更改集,请执行以下操作:创建和上传更改集,创建 AppExchange 包,以及上传 AppExchange 包

23 年冬季创建的增强型 LWR 站点可使用更改集进行部分部署 和以后。

您可以使用更改集移动使用数字 Experience Builder 站点的部分内容 体验组件类型。

  1. 在首选测试组织(如沙盒)中创建和测试站点。
  2. 在测试组织的“设置”中,在“快速查找”框中,输入“出站更改” 集,然后选择“出站更改集”。
  3. 创建更改集,然后单击“更改集组件”中的“添加” 部分。
  4. 选择“数字体验”组件类型。
  5. 从组件列表中选择要部署的内容,然后单击“添加到更改集”。提示
    • 要确定每个列出的组件属于哪个增强型 LWR 站点,请使用类型 列。Type 列使用命名约定 site/。MySiteName
    • 若要标识每个列出的组件所代表的内容,请使用“名称”列。名称 列使用命名约定 sfdc_cms__<contentType>/<contentName>。例如 名称 sfdc_cms__brandingSet/Build_Your_Own_LWR 表示名为 Build Your 的品牌集 拥有轻水堆。
  6. 单击“上传”,然后选择您的目标组织,例如生产组织。确保目标组织允许入站连接。入站和出站组织 必须具有部署连接。
  7. 从“设置”中,选择“入站更改集”,然后找到 您从源组织上传。
  8. 验证并部署更改集,使其在目标组织中可用。警告部署入站更改集时,它将覆盖相应的站点 目标组织中的内容。
  9. 手动重新配置目标组织站点中任何不受支持的项目。
  10. 为确保一切正常,请测试您的网站。然后发布更改 上线。

部署具有更改集的 Experience Cloud 站点的注意事项

迁移 Experience Builder 或 Salesforce 选项卡 + 带有更改集的 Visualforce 站点。

常规

  • 当您部署入站更改集时,它会覆盖 目标组织。因此,尽管不能使用更改集删除组件,但可以删除 Experience Builder 站点中的页面。例如,假设您从 沙盒中的Experience Builder站点,然后创建更新的出站更改集。什么时候 在目标组织(如生产组织)中重新部署更改集时,页面也 在那里删除了。
  • 如果您更新 Experience Cloud 站点模板,请确保您还更新了 在部署更改集之前定位组织。
  • 您无法部署到使用早期发行版的目标组织。例如 如果您的源组织位于 Summer ’19(API 版本 46.0)上,则无法部署到目标组织 在 Spring ’19 上(API 版本 45.0)。

管理

管理设置位于 Experience Workspaces 中。

  • 请记住添加“管理”|”成员添加到出站更改集。它们不会自动包含在内 依赖。
  • 对于在 17 年夏季版本之前在沙盒组织中创建的 Experience Cloud 站点,您 必须在迁移之前重新保存管理设置才能成功传输这些设置。
  • 在目标组织中发布站点之前,更改密码的设置会忘记 “密码”、“主页”、“自助注册”和“登录”页面似乎将恢复为默认值 值。
  • 要更新“会员”区域和“登录和注册”区域中的设置,您必须 在单独的更改集中部署更改。首先更新和部署“成员”区域 设置,然后更新和部署“登录和注册”设置。

导航菜单

导航菜单组件在 Experience Builder 站点中可用。

  • 对于链接到对象的菜单项,列表视图将重置为默认列表视图。 此外,标准对象的自定义列表视图不作为依赖项包含在内。
  • 部署带有其他菜单项的导航菜单会删除所有翻译 应用于目标环境中的现有菜单项。

建议

  • 不支持对建议名称的更新。如果更改 建议 在之前迁移过它的源组织中,目标组织会处理它 作为一项新的建议。
  • 不支持推荐图像。
  • 当您部署入站更改集时,它会覆盖目标组织的计划更改集 来自源组织的建议的建议。

增强型 LWR 站点的部分部署

  • 部分站点内容部署可用于增强的 LWR Experience Cloud 站点 创建于 23 年冬季或之后。
  • 若要部署部分网站内容,请确保目标组织包含现有网站 与源站点同名。
  • 将数字体验组件添加到出站更改集还会添加 组件到更改集的变体。例如,添加主视图组件 自动添加“主页”视图的所有翻译。

不支持的设置和功能

不支持以下项目。在部署入站更改集后手动添加它们。

  • 导航和特色主题
  • 观众 针对
  • 仪表板和参与度
  • 推荐图片
  • Experience Builder 中的品牌面板图像
  • Experience Workspaces中的以下管理设置:
    • “登录和注册”的“注册”部分中的“帐户”字段 面积
    • 选择要显示的登录选项选项 “登录和注册”区域的“登录”部分
    • “设置”区域
    • “富发布者应用”区域

使用元数据 API 部署 Experience Cloud 站点

使用元数据 API 将您的 Experience Cloud 站点从一个 Salesforce 组织移动到 另一个。在测试环境中设置和测试站点,然后检索站点的 数据并将其部署到您的生产组织。

根据网站框架的不同,以下元数据类型组合在一起以定义 网站。若要成功迁移站点,请使用元数据 API 检索调用来检索 org 的组件。网络表示 Experience Cloud 站点。包含管理设置,例如 作为页面覆盖、电子邮件和成员资格配置。定制网站包含域和页面设置信息,包括 indexPage、siteAdmin 和 URL 定义。DigitalExperienceBundle 和 DigitalExperienceConfig 或 ExperienceBundle  SiteDotCom所需的元数据类型因网站类型而异。代表 不同的设置和组件,例如页面、品牌集和 主题,构成一个网站。

对于冬季推出的增强型轻水堆站点 ’23(API 版本 56.0)、DigitalExperienceBundle 和 DigitalExperienceConfig 组合以提供基于文本的表示形式 您的网站元素和设置,但重新构想了更多 以内容为中心的结构。您可以检索可编辑的站点元数据,以及 以编程方式快速创建、更新、发布和部署网站。你 还可以部分部署增强型轻水堆站点。

对于非增强型轻水堆 站点,ExperienceBundle 提供基于文本的表示形式 站点的设置、页面和组件。您可以检索可编辑的网站 元数据,并快速创建、更新、发布和部分部署 以编程方式访问网站。

对于 Aura 站点,您可以选择使用 ExperienceBundle 或 SiteDotCom,但我们建议使用 体验捆绑包。在 Summer ’19(API 版本 45.0 及更早版本)之前, Network、CustomSite 和 SiteDotCom 元数据类型组合在一起以定义 光环网站。但是,检索 SiteDotCom 类型会生成人类不可读的二进制 .site 文件。请参阅 Experience Builder 站点的 ExperienceBundle。

为 Visualforce 站点,网络代表站点。

有关这些元数据类型的其他信息以及有关迁移的说明 data,请参阅元数据 API 开发 人员 指南和 Salesforce CLI 命令 参考资料。

所需元数据类型一目了然

用于部署网站的元数据类型因网站类型而异。

必需的元数据类型增强型 LWR 站点轻水堆站点Aura 站点Visualforce 网站
网络必填必填必填必填
定制网站必填必填必填必填
数字体验捆绑包必填
DigitalExperienceConfig 数字体验配置必填
体验捆绑包必填必填ExperienceBundle  SiteDotCom
网站DotCom必填

提示和注意事项

  • 在将数据迁移到另一个组织之前,请在目标组织中启用数字体验 并输入您在沙盒组织中使用的相同域名,以避免 出现错误。
  • 对于每个 Experience Cloud 站点,网络组件都具有唯一的名称和 URL 路径前缀。检索网络组件时,生成的 XML 文件 name 基于网络的名称。迁移时,API 会查看 文件名,如果存在,则更新站点。如果不存在,则 API 创建站点。如果有人在沙盒中更改了站点名称,然后尝试 要进行迁移,他们会看到一个错误。该 API 正在尝试使用 现有路径前缀。
  • 检查 CustomSite 的 XML 文件,确保所有依赖项都 带过来。如果缺少任何内容,请在 XML 文件中显式说明它们。
  • 除了前面描述的必需组件外,还包括所有 您的网站所需的其他组件。组件可以包括以下项 自定义对象、自定义字段、自定义 Lightning 组件和 Apex 类。
  • 要使用未锁定的软件包部署网络和配置文件组件,请创建一个 为每个组件单独解锁包并单独部署它们。
  • 使用 ExperienceBundle 部署 Aura 站点时,请确保 SiteDotCom 类型不包含在清单文件中。
  • 如果在“管理”|”设置,请确保源站点和目标站点具有匹配的值 用于 Network 组件中的 和 属性。picassoSitesite
  • 如果来宾用户配置文件有任何更改,请将配置文件作为一部分包括在内 的站点迁移。
  • 迁移用户配置文件时,用户将添加到生产中的站点 组织。然后,电子邮件将以与任何新网站相同的方式发送给会员。
  • 在部署过程中,请确保目标组织中的 NavigationMenu 开发人员名称与源中的开发人员名称相同 组织。
  • 如果 containerType 为 CommunityTemplateDefinition,则不能 通过元数据 API 更新现有的 NavigationMenu。
  • 要使用自定义模板部署 Aura 站点,请首先检索并部署 CommunityTemplateDefinition 和相关元数据类型,例如 CommunityThemeDefinition。然后检索并部署 ExperienceBundle 或 SiteDotCom 和相关元数据类型。
  • 部署带有其他菜单项的导航菜单会删除任何 应用于目标环境中现有菜单项的翻译。
  • 若要在移动站点时包含导航菜单,请使用 NavigationMenu 元数据类型。
  • 您无法部署到使用早期发行版的目标组织。为 例如,如果您的源组织使用的是 Summer ’19(API 版本 46.0),则不能 在 Spring ’19(API 版本 45.0)上部署到目标组织。
  • NavigationLinkSet 在 Winter ’20 中已弃用(API 版本 47.0),并替换为 NavigationMenu。
  • ExperienceBundle 不支持跨不同 API 进行检索和部署 版本。如果您尝试从早期版本升级 ExperienceBundle 元数据 API 版本到更高版本,例如,从 API 版本 48.0 到 49.0 – 执行以下步骤:
    1. 将 package.xml 清单文件中的 API 版本设置为 48.0 并部署 包。
    2. 然后,将 package.xml 中的 API 版本设置为 49.0。
    3. 要获取最新的 ExperienceBundle 更新,请检索包。
  • 部署站点时,有时会收到有关无效 ID 的警告消息 值。例如:The topicId property of component 9b8a4e98-e724-4292-bd3c-0813adf9ddc2 references an object with the ID value 0TO4R000000EGPEWA4. Occasionally, when deployed to a destination org, ID values can become invalid—for example, if the referenced ID doesn’t exist in the destination org. If you encounter component issues in your destination org, verify that the ID values are correct.在这些 在这种情况下,您可以成功部署站点,尽管有警告。 但是,我们建议在目标组织中验证对象 ID 组件中引用的仍然有效。如果 ID 不正确,请手动操作 更新 ID 以解决目标组织中的任何组件问题。 或者,如果它是您创建的自定义组件,请考虑 将对象 ID 替换为对象的 API 名称,以避免 将来的问题。

示例模板

以下示例包含您 可以通过元数据进行迁移 应用程序接口。

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://soap.sforce.com/2006/04/metadata">
    <allowInternalUserLogin>true</allowInternalUserLogin>
    <allowMembersToFlag>true</allowMembersToFlag>
    <allowedExtensions>txt,png,jpg,jpeg,pdf,doc,csv</allowedExtensions>
    <caseCommentEmailTemplate>unfiled$public/ContactFollowUpSAMPLE</caseCommentEmailTemplate>
    <changePasswordTemplate>unfiled$public/CommunityChangePasswordEmailTemplate</changePasswordTemplate>
    </communityRoles>
    <disableReputationRecordConversations>true</disableReputationRecordConversations>
    <emailSenderAddress>admin@myorg.com</emailSenderAddress>
    <emailSenderName>MyCommunity</emailSenderName>
    <enableCustomVFErrorPageOverrides>true</enableCustomVFErrorPageOverrides>
    <enableDirectMessages>true</enableDirectMessages>
    <enableGuestChatter>true</enableGuestChatter>
    <enableGuestFileAccess>false</enableGuestFileAccess>
    <enableInvitation>false</enableInvitation>
    <enableKnowledgeable>true</enableKnowledgeable>
    <enableNicknameDisplay>true</enableNicknameDisplay>
    <enablePrivateMessages>false</enablePrivateMessages>
    <enableReputation>true</enableReputation>
    <enableShowAllNetworkSettings>true</enableShowAllNetworkSettings>
    <enableSiteAsContainer>true</enableSiteAsContainer>
    <enableTalkingAboutStats>true</enableTalkingAboutStats>
    <enableTopicAssignmentRules>true</enableTopicAssignmentRules>
    <enableTopicSuggestions>true</enableTopicSuggestions>
    <enableUpDownVote>true</enableUpDownVote>
    <forgotPasswordTemplate>unfiled$public/CommunityForgotPasswordEmailTemplate</forgotPasswordTemplate>
    <gatherCustomerSentimentData>false</gatherCustomerSentimentData>
    <lockoutTemplate>unfiled$public/CommunityLockoutEmailTemplate</lockoutTemplate>
    <maxFileSizeKb>51200</maxFileSizeKb>
    <networkMemberGroups>
        <permissionSet>MyCommunity_Permissions</permissionSet>
        <profile>Admin</profile>
    </networkMemberGroups>
    <networkPageOverrides>
        <changePasswordPageOverrideSetting>VisualForce</changePasswordPageOverrideSetting>
        <forgotPasswordPageOverrideSetting>Designer</forgotPasswordPageOverrideSetting>
        <homePageOverrideSetting>Designer</homePageOverrideSetting>
        <loginPageOverrideSetting>Designer</loginPageOverrideSetting>
        <selfRegProfilePageOverrideSetting>Designer</selfRegProfilePageOverrideSetting>
    </networkPageOverrides>
    <picassoSite>MyCommunity1</picassoSite>
    <selfRegistration>true</selfRegistration>
    <sendWelcomeEmail>true</sendWelcomeEmail>
    <site>MyCommunity</site>
    <status>Live</status>
    <tabs>
        <defaultTab>home</defaultTab>
        <standardTab>Chatter</standardTab>
    </tabs>
    <urlPathPrefix>mycommunity</urlPathPrefix>
    <welcomeTemplate>unfiled$public/CommunityWelcomeEmailTemplate</welcomeTemplate>
</Network>

示例包 .xml 清单文件

清单文件定义您尝试检索的组件。以下 示例显示了 检索 Experience Builder 站点的所有组件。package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>Network</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomSite</name>
    </types>
    <types>
        <members>*</members>
        <name>ExperienceBundle</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexPage</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexComponent</name>
    </types>
    <types>
        <members>*</members>
        <name>Portal</name>
    </types>
    <types>
        <members>*</members>
        <name>Profile</name>
    </types>
    <types>
        <members>*</members>
        <name>Document</name>
    </types>
    <version>46.0</version>
</Package>

适用于 Experience Builder 站点的 ExperienceBundle

ExperienceBundle 元数据类型提供基于文本的不同 构成体验的设置和组件,例如页面、品牌集和主题 建筑商网站。无论是对于你自己的组织,还是咨询合作伙伴或 ISV,你都可以 使用首选开发工具以编程方式快速更新和部署站点, 包括适用于 VS Code 的 Salesforce 扩展、Salesforce CLI 或你喜欢的 IDE 或文本 编辑 器。

在 Summer ’19 版本(API 版本 45.0 及更早版本)之前,Network、CustomSite 和 SiteDotCom 元数据类型组合在一起以定义 Experience Builder 站点。但是,检索 SiteDotCom 类型生成一个非人类的二进制 .site 文件 读。通过检索 ExperienceBundle 类型而不是 SiteDotCom,您可以提取和 以人类可读的格式编辑粒度网站元数据,包含在三级文件夹中 结构。

局限性

  • 不支持托管包。

ExperienceBundle 结构

检索 ExperienceBundle 时,数据存储在三级文件夹结构中。

“体验”文件夹包含每个“体验生成器”的文件夹 组织中的站点。每个文件夹(在本例中customer_service)包含 子文件夹,用于定义站点并表示您在Experience Builder中访问的不同元素。每 子文件夹包含 .json 文件,其中包含可在本地编辑的属性 machine或scratch org,然后部署。site_name让我们仔细看看定义每个Experience Builder站点的文件。

文件夹内容
品牌集branding_set_name.json 定义了 网站的品牌设置属性。
配置site_name.json 定义了一些站点 设置,例如公共访问和渐进式渲染。languages.json 定义支持的语言。loginAppPage.json 和 mainAppPage.json 是单页应用程序 (SPA)。loginAppPage.json 用于需要 login,mainAppPage 用于所有其他页面。一 SPA 是加载单个 HTML 页面的 Web 应用。与传统的不同 网站,包括用户在其中导航的多个页面, SPA 由多个视图组成,这些视图以用户身份动态更新页面 与它交互。
路线每页包含一个名为 page_name.json 的文件,用于定义 URL 以及其他与路由相关的信息。
主题每个主题包含一个名为 theme_name.json 的文件,该文件定义了 主题。
变化每个变体包含一个名为 experienceVariation_name.json 的文件。你 可以使用体验变体来更改体验的默认行为 基于受众的构建器网站,例如品牌、页面变体、组件 可见性或组件属性。
视图每个视图包含一个名为 view_name.json 的文件。每个文件定义一个 SPA 视图,相当于最终用户的页面。视图由区域组成 在呈现的页面中包含其他区域或组件。

提示

在更新 Experience Builder 站点的 .json 文件之前,我们 建议复制站点的文件夹作为备份。

有关 ExperienceBundle 及其包含的文件的完整定义,请参阅元数据 API 开发人员 指南。

启用 ExperienceBundle 元数据类型

为 Aura 站点启用 ExperienceBundle 后,元数据 API 调用 ( 和 ) 和 Salesforce DX 操作 (, , 和 ) 使用 ExperienceBundle 类型,而不是 SiteDotCom。retrievedeploypullpushstatus

如果使用更改集来部署站点,则依赖项列表包括以下两项 键入 Site.com 和 1。1 现在表示 ExperienceBundle 而不是 SiteDotCom。MySiteNameMySiteNameMySiteName

注意

您无需为 LWR 站点启用 ExperienceBundle 元数据类型。轻水堆站点使用 默认为 ExperienceBundle。

  1. 在“设置”中,在“快速查找”框中输入, ,然后选择设置Digital Experiences
  2. 选择启用 ExperienceBundle 元数据 API
  3. 保存更改。

或者,您可以在使用临时组织创建临时组织时启用此功能 定义文件。(请参阅元数据覆盖范围 报告。

{
    "orgName": "Sample Org",
    "edition": "developer",
    "features": [
        "COMMUNITIES"
    ],
    "settings": {
        "experienceBundleSettings": {
            "enableExperienceBundleMetadata": true
        },
        "communitiesSettings": {
            "enableNetworksEnabled": true
        }
    }
}

使用元数据 API 检索和部署 ExperienceBundle

在元数据 API 中,清单文件定义您尝试检索的组件。 此示例显示 使用 ExperienceBundle 而不是 SiteDotCom 检索 Experience Builder 站点。package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomSite</name>
    </types>
    <types>
        <members>*</members>
        <name>ExperienceBundle</name>
    </types>
    <types>
        <members>*</members>
        <name>Network</name>
    </types>
    <version>46.0</version>
</Package>

检索 .zip 文件后,将其解压缩以访问和编辑文件。

请参阅部署和检索元数据 替换为 Zip 文件。

使用 Salesforce DX 检索和部署 ExperienceBundle

Salesforce 开发人员体验 (DX) 是一组工具,可简化整个 开发生命周期。它改善了团队发展和协作,促进了自动化 测试和持续集成,并使发布周期更加高效和 敏捷。如果您已设置 Salesforce DX 环境,则可以快速:

  • 使用以下命令检索组织中的所有Experience Builder站点sf project retrieve start
  • 使用以下方式部署更新sf project deploy start
  • 使用 或sf project deploy preview sf project retrieve preview
  • 检索可用模板的列表sf community list template
  • 使用以下方法创建站点sf community create
  • 使用sf community publish

如果您不熟悉 Salesforce DX,请查看这些很棒的资源。

避免迁移到增强型 LWR 站点时出现部署问题

从 24 年冬季开始,您无法再禁用增强的网站和内容平台, 它于 23 年冬季首次推出。因此,从 LWR 模板创建的任何站点都是 现在是默认增强的 LWR 站点。与使用 ExperienceBundle 的非增强型 LWR 站点不同 元数据类型,增强的 LWR 站点使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。但是,如果您在源组织(如沙盒)上创建了非增强型 LWR 站点 24 年冬季,您现在希望首次将站点部署到目标组织,例如 生产,元数据类型的这种差异可能会导致部署问题。

在这种情况下,我们不是在部署之前在目标组织上创建站点,而是 建议使用部署过程创建站点。否则,如果首先创建 目标组织上的站点,则新站点是增强的 LWR 站点,这意味着它使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。并且因为非增强 源组织上的 LWR 站点使用 ExperienceBundle(如果您随后尝试将其部署到目标) org,则由于元数据类型不匹配,部署失败。

但是,假设您在部署之前在目标组织中创建了站点。你能做什么 如何解决部署错误?

由于您无法删除 Experience Cloud 站点,因此我们建议您重命名站点并 更新目标组织中的站点 URL,使其不再与源中的值匹配 组织。此方法释放了部署过程,以便使用 源组织的值。

  1. 在目标组织中,在站点的“管理”工作区的“设置”页上,将 站点,使其与源组织中的站点不同。
  2. 在“设置”的“快速查找”框中,输入“自定义 URL”。
  3. 在“自定义 URL”中,找到网站的两个 URL。每个站点包括:
    • 映射到 ExperienceBundle 或 DigitalExperienceBundle 的 Site.com 社区 URL 和 DigitalExperienceConfig 元数据类型(视情况而定)映射到 CustomSite 的社区 URL
  4. 更改这两个站点 URL,以确保它们不再与 来源组织。
  5. 更新站点名称和 URL 后,使用更改集或 使用首选部署工具的元数据 API。
  6. 如果您使用的是元数据 API,请记住检索站点并包含网络和 CustomSite 类型,以允许系统在 目标组织。如果您使用的是更改集,请记住在之前重新创建更改集 部署。

部署经过身份验证的 LWR 站点的注意事项

从 23 年冬季开始,通过 Experience Builder 或 Connect API 创建新的 LWR 站点 不要在其 URL 末尾包含 /s。在 Winter 之前创建的经过身份验证的 LWR 站点的 URL ’23 仍包含 /s,如果沙盒和生产环境,此 URL 结构更新会影响部署 URL 不匹配。了解支持哪些部署方案以及如何解决不支持的方案 与 /s 相关的部署错误。

注意

所描述的方案假定沙盒和生产环境位于同一版本的 Salesforce的。不支持将站点从较新版本部署到较旧版本。

元数据 API 部署

  • 支持通过元数据 API 部署创建站点,无论源站点的 URL 包括 /s。如果源站点的 URL 包含 /s,则新目标站点的 URL 将包含 /s。如果 源站点的 URL 不包含 /s,新目标站点的 URL 不包含 /s。
  • 若要使用元数据 API 部署更新站点,请源站点的 URL 和目标站点的 URL 必须匹配。两个 URL 都必须包含 /s,否则任何一个 URL 都不能包含 /s。
  • 要解决与 /s 相关的元数据 API 部署错误,请将元数据包更新为 在源站点的 URL 中添加或删除 /s。确保源站点的 URL 与 目标站点的 URL。您不能在目标站点的 URL 中添加或删除 /s。

更改集部署

  • 支持通过更改集部署创建站点,无论源站点的 URL 包括 /s。如果源站点的 URL 包含 /s,则新目标站点的 URL 将包含 /s。如果 源站点的 URL 不包含 /s,新目标站点的 URL 不包含 /s。
  • 若要使用更改集部署更新站点,源站点的 URL 和目标站点的 URL 必须匹配。两个 URL 都必须包含 /s,否则任何一个 URL 都不能包含 /s。
  • 若要解决与 /s 相关的更改集部署错误,请重命名源站点或 通过API或Experience Builder的目标站点。重命名其中一个站点会创建一个 站点,而不是更新目标站点。不能将 /s 添加到 /s 中,也不能从 源站点的 URL 或目标站点的 URL。

开发安全站点: CSP、LWS 和 闪电 柜子

光环 和轻水堆站点 在 Experience Cloud 中 使用内容安全策略 (CSP) 和 Lightning Web 安全 (LWS) 或 Lightning Locker 来保护 这 网站免受恶意攻击和自定义代码漏洞。潜在影响的因素 当您开发自己的自定义组件时,使用第三方组件时,这些安全功能, 或在标记中添加自定义代码。

head

云解决方案提供商

CSP 是一种 W3C 标准,用于控制可在页面上加载的内容源。 CSP 规则在页面级别工作,适用于所有第三方组件和自定义代码。由 默认情况下,框架的标头仅允许从安全 (HTTPS) URL 加载内容 并禁止来自 JavaScript 的 XHR 请求。

Experience Builder 提供了不同级别的 CSP 脚本安全性。CSP 级别 特定于每个站点。

闪电储物柜 和 Lightning Web Security

这 Lightning Locker 架构层通过隔离单个 Lightning 来增强安全性 组件命名空间,并强制执行编码最佳实践。闪电 Locker 一直是 Lightning 组件和 Aura 的默认安全架构 体验中的站点 云。

LWS 旨在使您的组件更容易使用安全编码实践和 旨在取代闪电储物柜。与 Lightning Locker 一样,LWS 的目标是防止 Lightning 组件干扰或访问属于平台代码的数据 或来自其他命名空间的组件。但是,Lightning Web Security 的架构 使用不同的方法保护 Lightning Web 组件。

LWS 如何在组织和站点级别应用

管理员可以在组织级别启用 LWS 以在整个组织内使用,而不是 Lightning 通过将 Lightning Web Security 用于 Lightning Web 组件和 Aura 组件的 Locker 在“设置”的“会话设置”中设置。

此组织级别设置会影响 Aura 站点,因为在组织中启用 LWS 时,LWS 在站点级别替换 Lightning Locker。然后,如果您禁用 Lightning Locker 在 Experience Builder 中为 Aura 站点进行设置时,您实际上是在禁用 LWS。

LWR 站点有自己的 LWS 实例,因此 LWS 的组织设置对 LWR 没有影响 网站。如果在 LWR 站点中禁用 Lightning Locker,则该站点的 LWS 实例为 禁用,即使在组织中启用了 LWS 也是如此。

注意

默认情况下,会为所有新的Experience Builder站点启用严格CSP,这意味着 Lightning Locker 或 LWS 也已启用。要访问 Lightning Locker 设置 Experience Builder,选择“轻松的 CSP”。

对于 B2B 商店和 B2C 商店 LWR 模板 在 Commerce Cloud 中,默认情况下不启用 LWS。

下表总结了组织级别设置和站点级别设置在 Aura 或 LWR 站点。

Experience Cloud 站点框架网站级设置组织级别设置现场使用的 LWS 或储物柜
光环上上上
上检查上
检查上闪电储物柜
检查检查LWS系列
轻水堆上上上
上检查上
检查上LWS(站点的实例)
检查检查LWS(站点的实例)
  • 解决 Aura 站点中的 Lightning Locker 冲突 默认情况下,Experience Cloud 中的所有新 Aura
    站点都启用了 Lightning Locker。但是,有时,由于与 Lightning Locker 发生冲突,页面上的第三方组件或标记中的自定义代码无法按预期工作。在这种情况下,Salesforce 建议使用此处描述的解决方法之一。head
  • 允许第三方组件在 Lightning Locker 关闭
    时运行 如果您在 Experience Builder 站点中关闭 Lightning Locker,则必须将从托管包安装的任何第三方组件配置为在设计时可用并在运行时呈现。
  • 示例:Aura Sites
    中的 Adobe Analytics 和 Lightning Locker 由于 Adobe Analytics 会与 Aura 站点中的组件进行交互,因此 Lightning Locker 可能会产生意想不到的结果。建议的解决方法是在标记中使用 JavaScript 自定义事件来隔离 Adobe Analytics。然后,Adobe Analytics 可以与组件进行交互,而无需负责直接加载或引用该资源。head

解决 Lightning Locker 冲突 光环 网站

默认情况下,Lightning Locker 为所有新 光环 体验中的站点 云。但是,偶尔会有第三方组件在页面上或自定义 由于以下原因,标记中的代码无法按预期工作 与 Lightning Locker 冲突。在这种情况下,Salesforce 建议使用 此处介绍的解决方法。

head

使用 JavaScript 自定义事件

Lightning Locker 可防止第三方组件和自定义代码与 来自其他命名空间的资源,但不来自标记的资源。此限制意味着您的标记可以 包含绕过 Lightning Locker 并引入安全漏洞的自定义代码。headhead

要解决此限制,请隔离您的第三方 Aura 和 Lightning Web 组件,并 使用 构造函数的自定义代码 您的标记。第三方组件和自定义代码 然后,可以与资源交互,而无需负责加载或引用 该资源。CustomEventhead

必须通过事件传递到侦听器的任何数据都将在属性中传递,该属性是在初始化 事件。该属性映射到 dataLayer。自定义事件 然后,被分派给任何扩展的资源。有关使用自定义事件的示例,请参阅 Adobe Analytics 和 Lightning Locker。detaildetailheadEventTarget

警告

请注意使用 JavaScript 构造函数传递的数据,并确保使用量 安全。网页上运行的任何 JavaScript,包括任何第三方 App Exchange 您正在使用的组件可能会侦听您的事件名称并读取此内容 数据。CustomEvent

将 Aura 组件设置为 API 39.0

如果您的第三方组件或自定义代码未与 Aura 组件交互,则 预期,您可以将 Aura 组件设置为 Salesforce API 版本 39.0,这将禁用 组件的 Lightning Locker。请参阅《Lightning Aura 组件开发人员指南》中的禁用组件的 Lightning Locker。

警告

禁用 Aura 组件的 Lightning Locker 可以引入安全性 缺陷进入您的网站,并阻止组件在设计时可用,或者 在运行时呈现。

为了保持一致性和易于调试,请避免使用父 Aura 组件和子组件 组件。因此,请勿使用任何设置为 API 的 Aura 组件 组件层次结构中的版本 39.0,例如组件中的组件或组件 这扩展了另一个组件。

如果在组织中启用了 LWS,则在组件中设置 API 版本 39.0 不会禁用 LWS 对于组件。但是,LWS 可能允许 Lightning 的组件的行为 Locker 块,无需禁用它。

关闭 Lightning Locker

警告

仅将此解决方法用作最后的手段。

如果您在站点中关闭 Lightning Locker,则会为站点的所有第三方组件和自定义代码禁用它。后果可能是 范围广泛且出乎意料,例如在您的网站中引入安全漏洞。如果 第三方组件尚未启用,无法在没有 Lightning Locker 的情况下工作,它可以防止这种情况发生 组件在设计时可用,在运行时呈现。当闪电 Locker 已关闭,来自不同命名空间的组件可以与每个命名空间交互并访问每个 其他的文档对象模型 (DOM) 以及有关自定义资源交互的限制 与您的网站是放松的。

有关禁用 Lightning Locker 的更多信息,请参阅 Salesforce 帮助中的在 Experience Builder 站点中选择安全级别。

注意

如果在组织中启用了 LWS,则当您在 Aura 站点中禁用 Lightning Locker 时,您 实际上在站点中禁用 LWS。如果在 LWR 站点中禁用 Lightning Locker,则 站点的 LWS 实例被禁用,即使在组织中启用了 LWS 也是如此。

允许第三方组件在 Lightning Locker 关闭时运行

如果您在 Experience Builder 站点中关闭了 Lightning Locker,则任何第三方 从托管包安装的组件必须配置为在设计时可用 并在运行时渲染。

您可以从 Relaxed CSP 安全性中关闭 Lightning LockerYou can off Lightning Locker from the Relaxed CSP security 水平。

如果 LWS 在组织中启用,当您在 Aura 站点中禁用 Lightning Locker 时,您实际上是禁用的 LWS 在站点中。如果在 LWR 站点中禁用 Lightning Locker,则该站点的 LWS 实例 被禁用,即使在组织中启用了 LWS。 LWR 站点可以包含第三方库 而不禁用 Lightning Locker 或 LWS。有关详细信息,请参阅集成 在 LWR 站点中使用特权脚本标记的第三方库 经验 云。

警告

关闭 Lightning Locker 可能会给您的网站带来安全漏洞。 禁用 Lightning Locker 仅作为最后的手段。

配置 第三方光环 要运行的组件 不带 Lightning Locker

对于第三方 Aura 组件,托管包开发人员必须为 元件。lightningcommunity:allowInRelaxedCSP

配置 第三方闪电网络 要运行的组件 不带储物柜

对于第三方 Lightning Web 组件,托管软件包开发人员必须在组件配置文件的标记中配置该值。lightningCommunity__RelaxedCSPcapability

示例:Adobe Analytics 和 Lightning Locker 光环 网站

因为 Adobe Analytics 会与 光环 站点,Lightning Locker可能会产生意想不到的结果。建议的解决方法是隔离 Adobe Analytics,在标记中使用 JavaScript 自定义事件。然后,Adobe Analytics 可以与组件进行交互,而无需 负责直接加载或引用该资源。

head

提示

LWR 站点可以使用不同的策略来包含分析。为 有关详细信息,请参阅集成第三方库 在 LWR 站点中使用特权脚本标记以获得体验 云。

将 Adobe Analytics 包含在 光环 网站

将 Adobe Analytics 脚本和适用的事件侦听器添加到 使用标记的网站标记。

headscript

<script> 
    document.addEventListener('analyticsEvent', function(e) {
        //add logic here to tell your dataLayer about the event
        //dataLayer.action = e.detail.action;
        //dataLayer.label = e.detail.label;
        //or map payload to an AA library event
    });
    
    document.addEventListener('analyticsViewChange', function() {
    });
</script>
<script src="full-url-to-your-adobe-script" async></script>

使用自定义事件

对于要与 Adobe Analytics 交互的任何组件,请使用 该物业。此属性传递数据 通过事件发送到侦听器,并映射到 In your Markup 侦听器。这 然后,可以将自定义事件分派给扩展 的任何资源。

detaildataLayerheadEventTarget

document.dispatchEvent(new CustomEvent('analyticsEvent', {'detail': {action: 'click', label: 'Submitted Case'}}));

警告

请注意使用 JavaScript 构造函数传递的数据,并确保使用量 安全。在页面上运行的任何 JavaScript(包括 Adobe Analytics)都可能 侦听您的事件名称并读取此数据。CustomEvent

为 Aura 组件实现其他事件

如果Adobe Analytics与Aura组件交互,则还必须实施and事件。forceCommunity:routeChangeaura:locationChange

forceCommunity:routeChange跟踪视图更改 在 Lightning 组件中 框架。

<aura:component implements="forceCommunity:availableForAllPageTypes">
    <aura:handler event="forceCommunity:routeChange" action="{!c.handleRouteChange}" />
</aura:component>
handleRouteChange : function(component, event, helper) {
    document.dispatchEvent(new Event('analyticsViewChange'));
}

aura:locationChange表示哈希部分 浏览器位置栏中的 URL 已被修改。但是,更改哈希部分 的位置 URL 很少使用,例如,在 选项卡组件。

分析和改进 Experience Builder 站点性能

Salesforce Page Optimizer 会分析您的网站并识别影响的问题 性能。使用这些信息来优化您的设计并提高网站性能 成员。Page Optimizer 是 Chrome 网上应用店提供的免费插件。下载和 像安装任何 Chrome 扩展程序一样安装插件。

适用于:Salesforce Classic(并非在所有组织中都可用)和 闪电体验
适用于:EnterprisePerformanceUnlimited 和 Developer Edition
用户权限 需要
要自定义 Experience Cloud 站点,请执行以下操作:成为网站成员并创建和设置 经验或成为站点的成员,并查看设置和配置,以及 该站点中的体验管理员、发布者或构建者
要发布 Experience Cloud 站点,请执行以下操作:成为网站成员并创建和设置 经验或成为网站的成员,并且是其中的体验管理员或发布者 网站

要下载页面优化器,请在 Experience Builder 中单击设置左侧边栏,然后 ,然后点按“高级”。

安装后,页面优化器将与您的其他 Chrome 扩展程序一起定位。

见解

要分析您的网站,请导航到已发布的网站,加载页面,然后启动 页面优化器。

“见解”选项卡 (1) 根据 Web 应用程序的最佳实践评估您的页面 使用 Lightning 框架开发。此选项卡显示总体性能分数 (3) 以及各种分析规则的个人分数 (5)。查看详细信息和建议 操作中,单击每个规则。如需更多工作空间,请单击弹出窗口 (2)。

“见解”选项卡在提供建议时是保守的。如需进一步的见解, 考虑查看瀑布图、时间线、图表、成本和 “操作”选项卡。

要删除收集的指标,请单击清除 (4)。执行一些用户 操作以收集新指标,然后重新打开页面优化器。例如 要收集赞某个 Feed 项的效果指标,请清除效果指标,然后点击赞、 并重新打开页面优化器。

瀑布

“瀑布”选项卡显示所有网络请求和性能检测数据。点击 用于在边栏中查看上下文信息的行。单击每行左侧的箭头 以展开每行的信息。

时间线

“时间轴”选项卡提供每个组件渲染生命周期的配置文件。时间线 视图针对显示 Lightning 框架指标进行了优化,因此更易于解释 比 Chrome DevTools 。

图表

“图表”选项卡显示客户使用时有关内存和组件的趋势信息 您的页面。

组件

“组件”选项卡显示页面上每个组件的生命周期计数。此视图 帮助您识别潜在的组件泄漏和意外的渲染行为。使用 “组件”选项卡以及“成本”选项卡,用于全面了解组件性能。

成本

“成本”选项卡显示每个组件忙于处理其逻辑的时间量。这 时间越短,性能越好。

行动

“操作”选项卡显示页面上执行的所有操作的列表及其 计时信息。

出口

将您的分析导出到文件中,以便与您的开发和支持团队共享。

提交反馈

我们希望收到您的来信。分享您的意见、问题、请求和任何问题 找到。提交反馈。


将 Pardot 跟踪添加到您的体验构建器站点

Pardot 可以跟踪访问者在网站上的互动和活动,即使访问者 尚未转换为潜在客户。启用跟踪后,使用 Pardot 查看以下方面的报告 访客参与度,并根据现场活动自动对潜在客户进行评分。

  1. 在 Pardot 中,导航到要跟踪的广告系列。
  2. 点击查看跟踪 代码, 并复制代码。
  3. 访问要向其添加跟踪的站点的 Experience Builder。
  4. “设置”|”高级,单击“编辑头部标记”,然后粘贴到 Pardot 中 跟踪代码。

Experience Builder 站点是单页应用程序 (SPA),因此当用户导航到 网站上的不同页面,仅重新加载内容区域,而不是整个页面。这 Pardot 脚本将网站的首次加载记录为页面视图。修改脚本以允许 页面内的应用内导航,以便在 Pardot 中更准确地捕获。

  1. 在“编辑标题标记”窗口中,修改 Pardot 跟踪代码,以便在页面中进行更改 状态将添加到会话历史记录中。下面是一个包含修改的示例代码片段 著名的。
<script type='text/javascript'>
piAId = '{{%pardot-id-for-your-org%}}'; //no change from OOTB code (format: 123456)
piCId = '';
piHostname = '{{%pardot-hostname-for-your-org%}}'; //no change from OOTB code (format: www.yourpardottrackerdomain.com)
    
(function() {
  //patching the history push state function to include calling
  // the async_load function that sends data to Pardot
  var pushState = history.pushState;
  history.pushState = function() {
    pushState.apply(history, arguments);
    async_load(); 
  };
    
    function async_load(){0
        var s = document.createElement('script'); s.type = 'text/javascript';
        s.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + piHostname + '/pd.js';
        var c = document.getElementsByTagName('script')[0]; c.parentNode.insertBefore(s, c);
    }
    if(window.attachEvent) 
    { 
        window.attachEvent('onload', async_load);
         //attach event listener for browser history changes
         // for browsers that support attachEvent
         window.attachEvent('onpopstate', async_load);
    }
    else 
    { 
        window.addEventListener('load', async_load, false); 
        //add eventlistener for browser history changes
        // for all other browsers
        window.addEventListener('popstate', async_load, false);
    }
})();
    
    
</script>

更新网站的内容安全策略 (CSP) 设置,使 head 标记以 预期。

  1. 访问 Experience Builder |设置 |安全性
  2. 选择“宽松的 CSP:允许访问内联脚本”和“允许” 主机,然后在确认中单击“允许” 窗。
  3. “CSP 错误”下,可以看到被阻止的站点列表。单击要允许作为 Pardot 跟踪器的每个站点的允许 URL 域。

在 Pardot 和 Experience Cloud 之间成功集成后,您可以 根据访客的 Experience Cloud 网站准确跟踪页面浏览量并对潜在客户进行评分 导航。

将 CMS 与 你 Experience Builder 站点

内容管理系统 (CMS) 使您能够重用内容,而不是拥有 来复制它。使用 CMS,您可以将内容馈送到多个站点,还可以集中更新 它使它同时在任何地方保持最新状态。

Experience Cloud 提供两个 CMS 选项来满足您的需求。Salesforce CMS 内置于您的组织中 用于在组织中使用多个渠道创建、管理和组织内容。和CMS Connect 是一种工具,用于将第三方 CMS 中的内容嵌入到您的网站中。查看更多 有关这两个选项的信息,请参阅 CMS 开发人员 指南。

关于偏转的报告:偏转信号框架

事件是 当用户启动案例,然后查看解决其问题的偏转项时触发,并且 导致他们放弃此案。

lightningcommunity:deflectionSignal

例如,假设用户正在填写表单以创建客户案例,然后 在页面上看到一篇有用的文章。单击文章后,用户发现它很有帮助,并且 决定创建案例是不必要的。然后触发一个事件。活动内容包括 有关用户与文章交互的信息。用户的操作报告为 成功偏转,因为用户未创建案例。lightningcommunity:deflectionSignal

您可以通过目标对象 Community 的自定义报告类型来报告这些事件 案例偏转指标。信号在报告中显示为成功偏转、 挠度失败或潜在挠度。

注意

仅报告由经过身份验证的用户触发的事件。lightningcommunity:deflectionSignal

  • 案例创建偏转信号
    当用户偏离创建客户案例时,将在 Aura 站点中触发该事件。在用户查看文章或讨论后,系统会询问他们互动是否有帮助,以及他们是否想放弃他们的案例。lightningcommunity:deflectionSignal

案例创建偏转信号

活动是 在 Aura 站点中,当用户偏离创建客户案例时触发。在用户之后 查看文章或讨论时,系统会询问他们互动是否有帮助,以及他们是否 想放弃他们的案子。

lightningcommunity:deflectionSignal

注意

我们仅收集由身份验证触发的事件的数据 用户。lightningcommunity:deflectionSignal

您可以将 Case Deflection 组件配置为自动触发此事件 在Experience Builder中使用组件的“偏转度量度”属性。案例 挠度组件与联系支持表一起用于记录挠度 相互 作用。

属性

来自案例的偏转信号 挠度分量为 。sourceTypecaseCreateDeflectionModal

这是用户在主题中键入的内容 字段或案例创建表单的描述。是文章或讨论偏转项的 ID。sourcedestination

是 JavaScript 对象键值映射。 以下属性用于此类信号。payload

Payload 属性类型描述支持的值必填
deflectionAnswer字符串用户对第一个问题的回答,询问偏转项目是否 有益的。YESNOnull– 用户未投票
confirmationAnswer字符串用户对第二个问题的回答,询问他们是否希望停止 创建案例。YESNOnull– 用户未投票
state字符串弹出窗口在关闭之前最后处于的状态。MeasureDeflectionState– 用户 没有回答第一个问题ConfirmationQuestionState– 用户 没有回答第二个问题ConfirmationMessageState– 用户 回答了两个问题
caseCreated布尔指示用户是否创建了案例。true– 用户创建了案例false– 用户未创建 箱

例子

自定义 Aura 组件可以侦听此系统事件并根据需要进行处理。为 例如,如果用户发现内容没有帮助,则该组件可以启动另一个组件 过程。

下面是一个侦听系统事件的示例组件。

<aura:component implements="forceCommunity:availableForAllPageTypes">
    <aura:attribute name="message" type="String" required="false"/>
    <aura:handler event="lightningcommunity:deflectionSignal" action="{!c.handleSignal}"/>
    <lightning:formattedText value="{!v.message}"/>
</aura:component>

此客户端控制器示例处理系统事件并检查失败情况 挠度。也就是说,控制器会检查用户未找到 偏转项目很有帮助。

({
    handleSignal: function(component, event, helper) {
        var signal = event.getParams() || {},
            sourceType = signal.sourceType,
            payload = signal.payload;
        // Process case create deflection signals
        if (sourceType && sourceType === "caseCreateDeflectionModal") {
            if (payload && payload.deflectionAnswer === "NO") {
                component.set("v.message", "Sorry you didn't find that helpful.");
            }
            if (payload && payload.caseCreated === true) {
                component.set("v.message", "We Apologize For The Inconvenience. We'll get in touch with you shortly about your case.");
            }
        }
    }
})

自定义 Aura 组件充当外壳创建表单,外壳偏转组件可以 同时触发此事件。给定有效参数,将自动处理该事件,并 为报告而处理。此示例使用组件中的值触发一个事件 属性。lightningcommunity:deflectionSignal

fireCaseDeflectionSignal : function(component, shouldSubmitSourceTypeSignals) {
    var evt = $A.get("e.lightningcommunity:deflectionSignal");
    evt.setParams({
        sourceType: "caseCreateDeflectionModal",
        source: cmp.get("v.deflectionTerm"),
        destinationType: component.get("v.deflectionEntityType"),
        destination: component.get("v.deflectionEntityId"),
        payload: {
            deflectionAnswer: component.get("v.deflectionAnswer"),
            confirmationAnswer: component.get("v.confirmationAnswer"),
            state: component.get("v.deflectionState"),
            caseCreated: component.get("v.caseCreated")
        },
        shouldSubmitSourceTypeSignals: shouldSubmitSourceTypeSignals
    });
    evt.fire();
}

用户可以连续查看多个偏转项目,然后最终决定是否 创建或放弃案例。每个视图都会触发一个事件。如果要处理所有事件 作为单个批处理,设置为用户在其中的最终事件 放弃或创建案例。此示例根据 案例是否已创建。lightningcommunity:deflectionSignalshouldSubmitSourceTypeSignals=true

fireCaseCreatedSignal : function(component, caseCreated) {
    // Send all accumulated signals to the server to be processed
    var evt = $A.get("e.lightningcommunity:deflectionSignal");
    evt.setParams({
        sourceType: "caseCreateDeflectionModal",
        payload: {
            caseCreated: caseCreated
        },
        shouldSubmitSourceTypeSignals: true
    });
    evt.fire();
}

开发安全站点:经过身份验证的用户和来宾用户

实施可通过外部和未经身份验证访问的 Experience Cloud 站点时 来宾用户,请牢记这些安全注意事项。外部用户具有登录权限 您的 Experience Cloud 站点,但他们无法访问您的内部 Salesforce 组织。来宾用户是 互联网上任何可以访问您的可公开访问的页面和组件的人 Experience Cloud 站点。

  • 限制声明性访问
    授予查看对象的权限允许外部用户使用标准控制器查看该对象。启用了 Lightning 功能的 Experience Builder 站点和 Salesforce 选项卡 + Visualforce 站点中提供了标准控制器。这些控制器仅根据平台声明性权限授予访问权限。
  • 确定安全模型 对于每个用例,确定是实现自定义访问控制模型还是依赖声明性平台访问控制模型
    。建议尽可能使用平台声明性访问控制模型。但是,有时您的要求需要自定义访问控制模型。
  • 限制对 Apex 类的访问 仅允许来宾和外部用户访问他们必须调用的那些类
  • 安全性
    如果来宾或外部用户必须运行流,请覆盖流权限以仅授予对特定外部用户配置文件、权限集或站点来宾用户配置文件的访问权限,而不是允许用户运行所有流。尽可能避免在系统上下文中运行流,并限制对子流的访问。否则,请确保对这些流和子流实施过程访问控制。
  • SOQL 注入:
    清理传递到动态 SOQL 查询的用户控制数据。

限制声明性访问

授予查看对象的权限允许外部用户使用 标准控制器。Experience Builder 站点中提供了标准控制器,并且 启用了 Lightning 功能的 Salesforce 选项卡 + Visualforce 站点。这些控制器 仅基于平台声明性权限授予访问权限。

授予声明性访问权限,以仅创建、查看、修改或删除其 允许外部用户通过控制器进行访问,而无需中介。Salesforce的 平台包括可用于创建、读取、更新或删除的标准控制器 数据。标准 UI 控制器强制执行 平台的共享规则,在创建、读取、更新和删除 (CRUD) 权限中,以及 字段级安全性 (FLS)。如果向外部用户授予查看或更新 对象,他们能够执行操作。不要向任何对象授予过多的权限 如果您不希望行使这些权限。

未经身份验证的访客用户准则

请考虑以下有关记录 ID 加密和提供不同级别的准则 在选择声明性或自定义访问权限之前,对未经身份验证的来宾用户进行访问 控制模型。

  • 加密来宾用户
    的记录 ID 出于安全原因,除非您希望记录是公开的,否则不允许来宾用户按记录 ID 查找记录。当前宾用户创建记录并希望稍后访问该记录时,请创建一个加密字符串,该字符串使用记录 ID、记录创建时间戳和当前时间戳的组合。加密的字符串充当记录的唯一标识符,只有记录创建者才拥有。稍后,处理请求的 Apex 代码要求来宾用户提交加密字符串。该 Apex 代码解密字符串以获取记录 ID 和其他记录标识符,并检索或更新请求的记录。
  • 授予来宾用户读取记录的访问权限 当允许来宾用户访问读取记录
    数据时,将向公众公开数据。查看我们的指南,并设计实现,以允许来宾用户进行必要的访问,而不会影响你的数据。
  • 授予来宾用户创建记录的访问权限 因此,来宾用户可以创建对象记录
    ,请配置来宾用户配置文件以包括对所需对象的创建访问权限。
  • 授予来宾用户访问更新记录的权限 若要允许来宾用户更新记录
    ,请在系统上下文中执行操作,而不进行共享。在允许用户更新记录之前,最好验证以前提供给用户的加密令牌。若要确保记录正确无误,请验证有关记录的信息,例如其创建者。

加密来宾用户的记录 ID

出于安全原因,不允许来宾用户按记录 ID 查找记录,除非你 希望记录是公开的。当前宾用户创建记录并希望稍后访问该记录时, 创建一个加密字符串,该字符串使用记录 ID、记录创建时间戳、 和当前时间戳。加密字符串充当记录的唯一标识符 只有记录创建者有。稍后,处理请求的 Apex 代码需要 要提交加密字符串的来宾用户。该 Apex 代码解密字符串以获取 记录 ID 和其他记录标识符,并检索或更新请求的 记录。

提示

用户加密解密 AppExchange 包 提供类,该类使用 Apex 库进行加密和 解密,为您存储相关数据,并提供两个模板流。使用托管 package 来实现自定义的记录 ID 加密,或创建类似的 你自己的。UserCryptoHelperSystem.Crypto

授予来宾用户对读取记录的访问权限

当您允许来宾用户访问读取记录数据时,会将您的数据公开给 公共。查看我们的指南,并设计您的实施,以允许对 来宾用户,而不会损害您的数据。

警告

Summer ’20 版本添加了新的设置并更新了访客用户记录访问指南。截至 21 年冬季,将执行 20 年夏季更新中引入的准则。之后 Winter ’21 release,请使用本文档中描述的方法之一,因为之前的方法 方法不再起作用。

每次来宾用户请求读取记录数据时,响应都会在以下模式下运行 确定共享规则是否适用于请求。因为模式具有不同的安全性 顾及以下问题,请考虑数据的敏感性,以确定最适合您的方法 业务需求。您还可以使用单独的流或多个 Apex 类来运行某些请求 在一种模式下,其他请求在另一种模式下。

如何处理敏感信息

在将数据返回给未经身份验证的人之前,从记录中删除所有敏感信息 用户。出于安全原因,请勿使用记录 ID 等可猜测信息进行检索 包含敏感信息的记录。

与共享

与共享一起运行的记录请求无法访问记录,除非共享规则提供 来宾用户对它们的访问权限。如果出现以下情况,请考虑共享只读访问规则 是真的:

  • 您希望公开记录并可供任何人访问。
  • 可以使用共享规则选择目标记录,而不会公开其他记录 记录。

无共享

警告

在不共享的情况下实现请求时,请设计请求和 仔细响应数据,以确保不会无意中暴露组织的敏感数据 数据。

在系统模式下运行而不共享的记录请求执行操作 系统级访问并绕过共享规则。如果你不小心它的行为 执行以及如何执行它们,请求可以在运行时公开或修改记录数据 没有共享。在不共享的情况下运行的查询会将所有选定的记录公开给 公共。如果以下任一情况为真,请考虑不共享的系统模式:

  • 来宾用户需要的不仅仅是对记录的只读访问权限。
  • 您不希望记录是公开的。
  • 如果不公开其他记录,则无法选择记录。
  • 目标记录是父子关系和对子项的访问的一部分 记录受父记录的写入访问权限的限制。因为共享规则不能 向来宾用户授予写入访问权限,在此方案中运行请求而不共享。

用于记录选择的加密记录 ID

如果来宾用户创建了一条记录,并且以后必须访问该记录,请使用 记录创建时间戳,并将加密后的字符串返回给客户端。为客人提供 用户具有包含加密字符串的 URL,以便他们可以避免键入长字符串。 当他们请求对记录的读取访问权限时,请从 URL 中检索加密的字符串。自 选择记录,使用解密的记录 ID。

闪电组件

直接与对象字段链接的 Lightning 组件会自动执行 对象创建、读取、更新和删除 (CRUD) 权限和字段级安全性 (FLS) 检查以确定组件是否为用户显示。对于您不这样做的记录 与来宾用户共享时,CRUD 和 FLS 检查将失败,并且组件不会显示。自 使用 Lightning 组件显示这些记录,将其值设置为变量,以及 在 Apex 代码中将这些变量与对象的字段单独关联。由于此方法适用于自动 CRUD 和 FLS 检查,因此请实现 Lightning 组件遵循以下准则:

  • 在查询中,仅包含所需的记录字段。
  • 不要将敏感字段传递给客户端代码。
  • 仅将客户端所需的字段传递给客户端。发送到客户端的所有数据 是公开的。

代码示例

  • 共享示例代码:向来宾用户授予读取记录的访问权限
  • 不共享的示例代码:授予来宾用户在同一事务中创建和读取记录的权限
  • 不共享的示例代码:授予来宾用户创建记录并在以后读取记录的权限

流样

  • 共享示例流:为来宾用户提供读取记录的访问权限
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限

另见

  • Salesforce 帮助:保护访客用户的共享设置和记录 访问
  • Salesforce 帮助:共享规则
  • Salesforce 安全指南:共享规则

授予来宾用户创建记录的权限

因此,来宾用户可以创建对象记录,配置来宾用户配置文件以包括 为所需对象创建访问权限。要授予对对象的创建访问权限,必须授予对对象的读取访问权限。如果读取 不需要对该对象进行访问权限,我们建议删除该对象的所有权限,并且 在不共享控制器中运行创建逻辑。

提示

执行数据 对来宾创建的数据进行验证,以确保它不会影响自动化 过程。

记录 ID 和来宾用户

创建记录后,不要在对客户端的响应中包含记录 ID。创建 供以后访问的唯一记录标识符,在创建记录时对记录 ID 进行加密 时间戳,并将加密的字符串返回给客户端。

检索记录时,记录 ID 会自动包含在对象中。删除 对象的记录 ID,不要将其传递给客户端。

在 Apex 方法中创建和访问记录

来宾用户共享规则在事务完成后生效。如果 Apex 代码 共享创建并请求新创建的记录,而来宾用户依赖于 共享规则 若要访问记录,则读取请求失败,因为来宾共享规则 尚未生效。允许来宾用户创建记录并读取新创建的记录 记录,用关键字定义类。without sharing

Flow 中的记录创建和访问

在流程中,“创建记录”元素不会创建记录,直到面试执行 Screen、Local Action 或 Pause 元素。要在同一流中创建和读取相同的记录, 在记录创建和检索之间插入一个屏幕,或在 Apex 操作中读取记录。

样品

  • 示例流:授予来宾用户创建记录的访问权限
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限
  • 不共享的示例代码:授予来宾用户在同一事务中创建和读取记录的权限

另见

  • Salesforce 帮助:配置访客用户配置文件
  • 加密来宾用户的记录 ID

授予来宾用户访问更新记录的权限

若要允许来宾用户更新记录,请在系统上下文中执行操作,而无需 共享。在允许用户更新记录之前,请先验证加密令牌 作为最佳实践提供给用户。为确保其记录正确无误,请验证 有关记录的信息,例如其创建者。

警告

Summer ’20 版本添加了新的设置并更新了访客用户记录访问指南。截至 21 年冬季,将执行 20 年夏季更新中引入的准则。之后 21 年冬季版本,必须使用无共享模式,因为无法使用共享规则 授予来宾用户对记录的更新访问权限。

Lightning 组件和访客用户

直接与对象字段链接的 Lightning 组件会自动执行 对象权限和字段级安全性 (FLS) 检查以确定组件是否 为用户显示。如果启用了“保护来宾用户记录访问”设置,则无法授予来宾用户更新记录的访问权限。在这种情况下, 需要更新权限的对象权限检查失败,组件不会 显示。要使用 Lightning 组件处理访客用户输入,请使用变量来设置 闪电组件。然后将这些变量与记录的字段分别关联 在 Apex 代码中。因为此方法适用于自动对象权限和 FLS 检查,请按照以下准则实施您的 Lightning 组件:

  • 使用服务器端代码检索记录并验证它是否是所需的记录 在执行更新之前进行更新。
  • 不要将记录字段传递给客户端,除非您希望将其显示给用户。 您发送给客户端的任何数据都是公开的。
  • 不要将记录 ID 传递给客户端。不接受来自客户端的记录 ID。自 为记录创建唯一标识符,将记录 ID 加密为字符串。
  • 使用服务器端逻辑将更新限制为仅对所需字段进行更新。请勿使用 用于确定服务器端行为的客户端代码。
  • 使用服务器端逻辑验证来自客户端的数据,然后代码执行 更新。

声明式访问控制模型示例

这些代码和流示例使用声明性访问控制模型来提供 未经身份验证的来宾用户访问读取记录。

  • 共享示例流:授予来宾用户读取记录
    的访问权限 在此示例流中,来宾用户输入日期范围,然后查看该范围内的事件。来宾用户具有对具有共享规则的记录的读取访问权限,因此来宾用户配置文件确定流可以访问哪些字段。
  • 共享示例代码:授予来宾用户读取记录
    的访问权限 在此代码示例集合中,来宾用户输入日期范围,然后查看该范围内的事件。来宾用户通过共享规则对记录具有读取访问权限。

共享示例流:为来宾用户提供读取记录的访问权限

在此示例流中,来宾用户输入日期范围,然后查看该日期范围内的事件 范围。来宾用户具有对具有共享规则的记录的读取访问权限,因此来宾用户 配置文件确定流可以访问哪些字段。

Important

在向来宾用户授予读取访问权限之前,请参阅授予 来宾用户访问读取记录。

流配置

由于来宾用户可以通过共享规则访问记录,因此请将“如何”设置为“如何” 将“流”设置运行到“用户”或“系统上下文”(Based on Flow 是如何启动的。

输入日期范围 (1)

流程中的第一个元素是显示开始日期和结束日期输入字段的屏幕。 该元素将输入日期保存在变量和 中。Start_DateEnd_Date

获取活动 (2)

下一个元素是“获取记录”查询,该查询选择符合以下条件的事件:

  • 事件大于变量。StartDateTimeStart_Date
  • 事件小于变量。EndDateTimeEnd_Date
  • 事件的值为 。isPrivateFalse
  • 事件的值为 。isArchivedFalse

该元素将所选事件保存在变量中。GetEvents

循环唱片 (3)

Loop 元素循环遍历变量中的每个事件。GetEvents

在循环中,Assignment 元素将每个事件的 、 、 和 附加到 一个字符串。StartDateTimeEndDateTimeSubjectLocation

展会活动 (4)

最后一个元素是显示包含所有事件的字符串的屏幕。

共享示例代码:向来宾用户授予读取记录的访问权限

在此代码示例集合中,来宾用户输入日期范围,然后查看 该范围内的事件。来宾用户通过共享对记录具有读取访问权限 规则。

重要

在向来宾用户授予读取访问权限之前,请参阅向来宾用户授予读取记录的访问权限。

Aura 组件:DisplayEvents.cmp

此示例 Aura 组件显示两个组件,用户在其中输入开始日期和结束日期 以查看事件。组件 显示每个事件的 、 、 和 。lightning:inputlightning:cardStartDateTimeEndDateTimeSubjectLocation

<aura:component controller="GuestUserEventsAuraController">

    <aura:attribute name="events" type="Event[]"/>
    <aura:attribute name="StartDate" type="String" default=""/>
    <aura:attribute name="EndDate" type="String" default=""/>

    <lightning:input type="datetime" name="StartDate" value="{!v.StartDate}" aura:id="StartDate" label="Start after: " required="true"/>
    <lightning:input type="datetime" name="EndDate" value="{!v.EndDate}" aura:id="EndDate" label="End before: " required="true"/>
    <lightning:button name="Submit" variant="brand" label="Find events" title="Find events" onclick="{!c.handleSearch}"/>
    
    <lightning:card title="Events">
        <p class="slds-p-horizontal--small">
            <aura:iteration items="{!v.events}" var="event">
                {!event.Subject} ({!event.Location}) starts at {!event.StartDateTime} and ends at {!event.EndDateTime} <br/>
            </aura:iteration>
        </p>
    </lightning:card>
</aura:component>

组件控制器:DisplayEventsController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    handleSearch : function(component, event, helper) {
        helper.doSearch(component, event, helper);
    }
})

JavaScript 帮助程序:DisplayEventsHelper.js

此 JavaScript 帮助程序创建一个异步请求来查找两者中的事件 用户提交的时间戳,并定义请求时要执行的操作 完成。

({
        doSearch : function(component, event, helper) {
            var start_date = component.find("StartDate").get("v.value");
            var end_date = component.find("EndDate").get("v.value");
            var action = component.get("c.searchEvents");
            action.setParams({
                "start_date": start_date,
                "end_date": end_date
            });
            action.setCallback(this, function(response){
                component.set("v.events", response.getReturnValue());
            });
            $A.enqueueAction(action);
        }
})

Apex 控制器:GuestUserEventsAuraController.cls

此示例 Apex 控制器接收从 JavaScript 查找记录的调用 助手。它选择符合以下条件的事件:

  • 事件更大 比参数。StartDateTimeStart_Date
  • 事件小于 参数。EndDateTimeEnd_Date
  • 事件的值为 。isPrivateFalse
  • 事件的值为 。isArchivedFalse

查询为每个事件返回以下字段:

  • StartDateTime
  • EndDateTime
  • Location
  • Subject
  • Id

由于来宾用户不需要记录 ID,因此循环会将所有其他字段复制到新的 Event 对象。然后,我们 将新对象添加到新列表,并将该列表返回给客户端。for

来宾用户有权访问具有共享规则的记录,因此我们定义了类 替换为关键字。with sharing

警告

Internet 上的任何系统或个人都可以调用方法。保护 方法。确保查询选择 仅所需的记录和必填字段。@AuraEnabled

public with sharing class GuestUserEventsAuraController {
	
    @AuraEnabled
    public static List<Event> searchEvents(Datetime start_date, Datetime end_date){
        List<Event> results = [SELECT Event.Subject,
                                  Event.StartDateTime,
                                  Event.EndDateTime,
                                  Event.Location
                FROM Event 
                WHERE Event.EndDateTime<:end_date AND 
                      Event.StartDateTime>:start_date AND 
                      Event.isPrivate=False AND 
                      Event.isArchived=False];

        List<Event> filtered_events = new List<Event>();
        for (Event event : results) {
            Event new_event = new Event(Subject = event.Subject, 
                                                              StartDateTime = event.StartDateTime, 
                                                              EndDateTime = event.EndDateTime,
                                                              Location = event.Location);
            filtered_events.add(new_event);
        }
        return filtered_events;
    }
}

自定义访问控制模型示例

这些代码和流示例使用自定义访问控制模型来提供 未经身份验证的来宾用户访问以创建记录。

  • 不共享的示例代码:授予来宾用户创建记录并在以后
    读取记录的权限 这些代码示例支持两个单独的交互。在第一次交互中,来宾用户创建一个案例。为了允许将来访问,Apex 方法将记录 ID 替换为加密字符串。当前宾用户稍后想要读取案例时,他们会输入加密的字符串。Apex 方法解密字符串并使用它来检索大小写。
  • 示例流:授予来宾用户创建记录的访问权限 在此示例流中,来宾用户输入反馈,流将其存储在自定义对象记录
    中。来宾用户在创建后无权读取记录。
  • 不共享的示例代码:授予来宾用户在同一事务
    中创建和读取记录的权限 在此代码示例集合中,来宾用户输入详细信息以报告支持问题,Apex 代码创建案例。Apex 方法检索新记录,Aura 组件在创建后向来宾用户显示部分记录。Apex 代码在不共享的情况下运行,因为我们不依赖对象权限和平台共享来允许来宾用户访问记录。
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限 在此示例流中,来宾用户输入详细信息以报告支持问题,然后流
    创建案例。来宾用户创建记录后,默认活动用户将成为记录的所有者,并且来宾用户无法直接访问该记录。然后,流检索新案例以获取案例和字段,并将这些字段显示给来宾用户。由于来宾用户在创建记录后不拥有该记录,并且流必须检索该记录,因此该流在不共享的情况下运行。CaseNumberStatus
  • 不共享的示例代码:授予来宾用户创建记录并在以后
    更新记录的权限 这些代码示例支持两个单独的交互。在第一次交互中,来宾用户创建一个案例。出于安全原因,Apex 方法将记录 ID 替换为加密字符串。当来宾用户想要稍后关闭案例时,他们会输入该加密字符串。Apex 方法解密字符串以获取记录 ID,使用记录 ID 选择案例,并更新案例的状态。

不共享的示例代码:授予来宾用户创建记录和读取记录的权限 后

这些代码示例支持两个单独的交互。在第一次互动中,客人 用户创建案例。为了允许将来访问,Apex 方法将记录 ID 替换为 加密的字符串。当来宾用户稍后想要阅读案例时,他们会输入 加密字符串。Apex 方法解密字符串并使用它来检索大小写。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示来宾用户可以输入的多个组件 有关新案例或现有案例中的令牌的详细信息。创建记录后,组件将显示新的 案例的加密令牌或与令牌匹配的案例的状态。lightning:card

出于演示目的,此示例使用来宾用户可以在其中输入的字段 他们案件的令牌。若要实现此方案,请为来宾用户提供链接 包含令牌,并从 URL 中检索令牌。

<aura:component controller="GuestUserCreateForLater">
    <aura:attribute name="caseID" type="String"/>
    <aura:attribute name="case_status" type="String"/>
    <aura:attribute name="subject" type="String"/>
    <aura:attribute name="description" type="String"/>
    <aura:attribute name="email" type="String"/>

     Enter details to create a new case
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    <lightning:button name="submit" variant="brand" label="Create case" title="Create case" onclick="{!c.submitCase}"/>
        
    <aura:if isTrue="{!v.caseID}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                New case created:
                <p>{!v.caseID}</p>
            </p>
        </lightning:card>
    </aura:if>

    Or enter an existing case token to view the status of the case
    <lightning:textarea name="existing_case" required="false" label="Existing case token" aura:id="existing_case"/>
	<lightning:button name="submit" variant="brand" label="Lookup case" title="Lookup case" onclick="{!c.lookupCase}"/>
    <aura:if isTrue="{!v.case_status}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                Case status: 
                <p>{!v.case_status}</p>
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    }
    lookupCase : function(component,event,helper){
        helper.getCase(component,event,helper);
    }
})

JavaScript 帮助程序:DisplayCaseHelper.js

此 JavaScript 帮助程序有两种方法:makeCase()该方法创建一个 异步请求,以使用提交的数据创建案例。当 请求完成时,回调会将新案例的唯一令牌存储在 使用的变量中的字段 由 Aura 组件提供。makeCase()caseIDgetCase()该方法使用令牌 由来宾用户输入,以异步检索匹配的案例 令牌。该方法的回调捕获来自 Apex 的响应 方法并将值存储在变量中。getCase()case_status

({
    makeCase : function(component, event, helper) {
        var subject = component.find("subject").get("v.value");
        var description = component.find("description").get("v.value");
        var email = component.find("email").get("v.value");

        var action = component.get("c.CreateCase");
        action.setParams({
            "subject": subject,
            "description": description,
            "email": email
        });
        action.setCallback(this, function(response){
            component.set("v.caseID", response.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    getCase : function(component,event,helper){
        var case_token = component.find("existing_case").get("v.value");
        var action = component.get("c.GetCase");
        action.setParams({
            "token":case_token
        });
        action.setCallback(this, function(response){
            component.set("v.case_status", response.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})

Apex 控制器:GuestUserCreateForLater.cls

此示例 Apex 控制器接收用于创建和检索案例的调用。它使用用户加密解密 AppExchange 包来加密和解密数据。CreateCase()Apex 方法创建一个 大小写与来宾用户的输入。创建记录后,它会生成一个 来自记录 ID、记录字段和当前记录的加密字符串 时间戳。Apex 方法返回加密的字符串。CreateCase()CreatedDateGetCase()该方法解密 提供的字符串,验证结果,并传递解密的记录 ID 并为帮助程序方法创建时间戳以检索原始记录。 响应是记录的状态。GetCase()

使用关键字定义类,因为我们不依赖于对象权限和平台共享 创建和访问记录。without sharing

警告

Internet 上的任何系统或个人都可以调用方法。确保查询可以 仅检索新创建的记录,并仅选择必填字段。@AuraEnabled

public class without sharing GuestUserCreateForLater {
    
    @AuraEnabled
    public static String CreateCase(String subject, 
                                         String description, 
                                         String email){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email);
        insert new_case;
        
        List<Case> results = getCase(new_case.Id);


        String encryptedID = ued.UserCryptoHelper.doEncrypt(results[0].Id+'|'+ results[0].CreatedDate.getTime() +'|'+System.DateTime.now().getTime());
        return encryptedID;
    }
    
    public static final Long validTimestampMinutes = 10;

    @AuraEnabled
    public static String GetCase(String token){
        String status = 'Case not found';
        String decrypted_token = '';
        try {
            decrypted_token = ued.UserCryptoHelper.doDecrypt(token);
        } catch(Exception e) {
            return status;
        }
        
        String[] decrypted_parts = decrypted_token.split('\\|');
        String decryptedRecordId = decrypted_parts[0];
        String created_timestamp = decrypted_parts[1];
        String original_request_timestamp = decrypted_parts[2];

        
        
        if( isTimestampValid(System.Long.valueOf(original_request_timestamp)) ){
        	List<Case> caseList = getCase(decryptedRecordId, created_timestamp);
        	if(caseList.size() == 1){
    	        status = caseList[0].Status;
	    	}else{
                status = 'Case not found';
        	}
    	}
        return status;

    }

    private static List<Case> getCase(String caseID, Datetime created_date)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate, Case.Status  
        FROM Case 
        WHERE Case.Id=:caseID AND Case.CreatedDate=:created_date];
        return results;
    }

    private static Boolean isTimestampValid(Long timestamp)
    {
        return ((System.now().getTime() - timestamp) / 60000) < validTimestampMinutes;
    }
}

注意

如果要加载高度敏感的信息,请考虑以下附加信息之一 提高安全性的措施。

  • 要求用户输入与以下数据相关的其他信息 他们试图阅读或修改,只有他们自己知道。
  • 要求用户登录才能读取或修改数据。

示例流:授予来宾用户创建记录的访问权限

在此示例流中,来宾用户输入反馈,流将其存储在自定义流中 对象记录。来宾用户在创建后无权读取记录。

重要

在向来宾用户授予记录创建访问权限之前,请阅读向来宾用户授予创建记录的访问权限。

自定义Feedback__c对象

此方案使用 Feedback__c 自定义对象来存储来自来宾用户的反馈。一个 Feedback__c自定义对象都包含以下字段,按字母顺序列出:Email__c必填。来宾用户的电子邮件地址。数据类型: 电子邮件Score__c必填。来宾用户输入的反馈分数。可能的值为 、 、 、 、 、 。012345Additional_comments__c来宾用户输入的任何其他反馈。数据类型:长文本区域

流配置

因为流不需要对任何记录的读取访问权限,并且我们不依赖于对象 权限,将“如何运行流”设置设置为“系统” 无共享上下文 – 访问所有数据

意见反馈表 (1)

流中的第一个元素是显示以下组件的屏幕:

  • 用户电子邮件地址的电子邮件组件。
  • 用户反馈分数的 Slider 组件,设置为允许从 0 到 5.
  • 用于任何其他注释的长文本区域组件。

创建记录 (2)

下一个元素是创建Feedback__c记录的 Create Records 元素。

片尾画面 (3)

最后一个屏幕元素显示文本,以感谢用户的反馈。

不共享的示例代码:授予来宾用户在其中创建和读取记录的权限 交易

在此代码示例集合中,来宾用户输入详细信息以报告支持 问题和 Apex 代码创建一个案例。Apex 方法检索新记录和 Aura 组件在创建后向来宾用户显示部分记录。Apex 代码运行 没有共享,因为我们不依赖对象权限和平台共享来 允许来宾用户访问记录。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示用户在其中输入详细信息的多个组件 关于案件。创建后,该组件将显示新案例的案例编号和 地位。lightning:card

<aura:component controller="GuestUserCreateCase">

    <aura:attribute name="caseNumber" type="String"/>
    <aura:attribute name="status" type="String"/>
    <aura:attribute name="subject" type="String" default=""/>
    <aura:attribute name="description" type="String" default=""/>
    <aura:attribute name="email" type="String" default=""/>
    <aura:attribute name="name" type="String" default=""/>
    <aura:attribute name="reason" type="String"/>    
    <aura:attribute name="type" type="String" default=""/>

    <lightning:select name="select" label="Reason" required="true" value="{!v.reason}"  aura:id="reason">
        <option value="installation">Installation</option>
        <option value="equipmentcomplexity">Equipment Complexity</option>
        <option value="performance">Performance</option>
        <option value="breakdown">Breakdown</option>
        <option value="equipmentdesign">Equipment Design</option>
        <option value="feedback">Feedback</option>
        <option value="other">Other</option>
    </lightning:select>
    
    <lightning:select name="type" label="Type" required="true" value="{!v.type}"  aura:id="type">
        <option value="mechanical">Mechanical</option>
        <option value="electrical">Electrical</option>
        <option value="electronic">Electronic</option>
        <option value="structural">Structural</option>
        <option value="other">Other</option>
    </lightning:select>
    
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="name" label="Name" required="true" value="{!v.name}" aura:id="name"/>
    
    
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    
    <lightning:button name="submit" variant="brand" label="Submit case" title="Submit case" onclick="{!c.submitCase}"/>
    
    <aura:if isTrue="{!v.caseNumber}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                {!v.caseNumber} has status {!v.status}.
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    }
})

JavaScript 帮助程序:DisplayCaseHelper.js

此 JavaScript 帮助程序创建一个异步请求,以使用 提交的数据。请求完成后,回调会存储案例编号和 Aura 组件使用的变量中的案例状态。

({
        makeCase : function(component, event, helper) {
            var subject = component.get("v.subject");
            var description = component.get("v.description");
            var email = component.get("v.email");
            var name = component.get("v.name");
            var reason = component.get("v.reason");
            var type = component.get("v.type");

            
            var action = component.get("c.CreateCase");
            action.setParams({
                "subject": subject,
                "description": description,
                "email": email,
                "name": name,
                "reason": reason,
                "caseType": type
            });
            action.setCallback(this, function(response){
                component.set("v.caseNumber", response.getReturnValue()[0]);
                component.set("v.status", response.getReturnValue()[1]);
            });
            $A.enqueueAction(action);
        }
})

Apex 控制器:GuestUserCreateCase.apxc

此示例 Apex 控制器创建记录,检索新记录,然后返回 从新记录到客户端的必填字段。因为对象权限 并且不使用平台共享,此控制器在不共享的情况下运行。

为了避免意外暴露记录数据,该方法仅返回 和 字段。CreateCaseCaseNumberStatus

警告

Internet 上的任何系统或个人都可以调用类。确保方法 仅返回新记录中的必填字段。@AuraEnabled

public without sharing class GuestUserCreateCase {
    
    @AuraEnabled
    public static List<String> CreateCase(String subject, 
                                         String description, 
                                         String email,
                                         String name,
                                         String reason,
                                         String caseType,
                                         String phone){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email,
                                 SuppliedName=name,
                                 Reason=reason,
                                 Type=caseType,
                                 SuppliedPhone=phone);
        insert new_case;
                                             
        List<Case> results = getCase(new_case.Id);

        List<String> response = new List<String>();
        response.add(results[0].CaseNumber);
        response.add(results[0].Status);
        return response;

    }

    private static List<Case> getCase(String caseID)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate 
        FROM Case 
        WHERE Case.Id=:caseID];
        return results;
    }

}

不共享的示例流:为来宾用户提供在一个中创建和读取记录的权限 流

在此示例流中,来宾用户输入详细信息以报告支持问题和流 创建案例。来宾用户创建记录后,默认活动用户将成为所有者 的记录,来宾用户无法直接访问它。然后,该流检索 New case 获取案例的 AND 字段,并将这些字段显示给来宾用户。 由于来宾用户在创建后不拥有该记录,并且流必须检索 记录时,流在不共享的情况下运行。

CaseNumberStatus

重要

在向来宾用户授予创建和读取访问权限之前,请先阅读授予来宾用户读取记录的访问权限和授予来宾用户创建记录的访问权限。

流配置

由于流会创建记录,然后在不共享的情况下检索该记录,因此请将“如何运行流”设置设置为“不使用系统上下文” 共享 – 访问所有数据

案例表格 (1)

流中的第一个元素是显示以下输入组件的屏幕:

  • 公司名称的文本组件
  • 提交者姓名的 Name 组件
  • 提交者电子邮件地址的电子邮件组件
  • 提交者电话号码的电话组件
  • 一个 Picklist 组件,其中包含记录类型字段中的选项值Type_Options
  • 一个 Picklist 组件,其中包含记录类型字段中的选项值Reason_Options
  • 案例主题的文本组件
  • 用于描述案例的长文本区域组件

作业 (2)

第二个元素将输入组件中的数据分配给新的记录变量。Case

创建记录 (3)

下一个元素是“创建记录”元素,该元素使用记录变量创建案例记录。除了信息 由访客用户输入,设置元素配置以定义案例的来源字段 如。CaseWeb

获取记录 (4)

“获取记录”元素通过其字段检索新记录,该字段由“创建记录”元素自动定义。这 检索到的记录存储在新记录中 变量。IdCase

片尾画面 (5)

最后一个屏幕元素显示 Get 中的 Case 和字段 Record 元素的记录变量。CaseNumberStatusCase

不共享的示例代码:授予来宾用户创建记录和更新记录的权限 后

这些代码示例支持两个单独的交互。在第一次互动中,客人 用户创建案例。出于安全原因,Apex 方法将记录 ID 替换为 加密字符串。当来宾用户想要稍后关闭案例时,他们会输入该案例 加密字符串。Apex 方法解密字符串以获取记录 ID,使用记录 ID 以选择案例,并更新案例的状态。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示用于创建和关闭记录的组件。

若要创建案例,来宾用户使用组件输入案例详细信息。记录后 创建时,组件显示 新案例的加密令牌或与令牌匹配的案例的状态。lightning:card

出于演示目的,此示例显示一个组件,其中来宾用户 直接输入案例的令牌。若要实现此方案,请提供来宾用户 替换为包含令牌的链接,然后从 URL 中检索令牌。

<aura:component controller="GuestUserCreateForLater">
    <aura:attribute name="caseID" type="String"/>
    <aura:attribute name="case_status" type="String"/>
    <aura:attribute name="subject" type="String"/>
    <aura:attribute name="description" type="String"/>
    <aura:attribute name="email" type="String"/>

     Enter details to create a new case
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    <lightning:button name="submit" variant="brand" label="Create case" title="Create case" onclick="{!c.submitCase}"/>
        
    <aura:if isTrue="{!v.caseID}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                New case created:
                <p>{!v.caseID}</p>
            </p>
        </lightning:card>
    </aura:if>

    Or enter an existing case token to close the case
    <lightning:textarea name="existing_case" required="false" label="Existing case token" aura:id="existing_case"/>
	<lightning:button name="submit" variant="brand" label="Close case" title="Close case" onclick="{!c.updateCase}"/>
    <aura:if isTrue="{!v.case_status}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                Case status: 
                <p>{!v.case_status}</p>
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    },
    updateCase : function(component,event,helper){
        helper.updateCase(component,event,helper);
    }
})

JavaScript 帮助程序:CaseHelper.js

此 JavaScript 帮助程序有两种方法:makeCase()该方法创建一个 异步请求,以使用提交的数据创建案例。当 请求完成时,回调会将新案例的唯一令牌存储在 使用的变量中的字段 由 Aura 组件提供。makeCase()caseIDupdateCase()该方法使用 来宾用户输入的令牌,以异步更新大小写 匹配令牌。该方法的回调捕获来自 Apex 方法并将值存储在变量中。updateCase()case_status

({
    makeCase : function(component, event, helper) {
        var subject = component.find("subject").get("v.value");
        var description = component.find("description").get("v.value");
        var email = component.find("email").get("v.value");

        var action = component.get("c.CreateCase");
        action.setParams({
            "subject": subject,
            "description": description,
            "email": email
        });
        action.setCallback(this, function(response){
            component.set("v.caseID", response.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    updateCase : function(component,event,helper){
        var case_token = component.find("existing_case").get("v.value");
        var action = component.get("c.UpdateCase");
        action.setParams({
            "token":case_token
        });
        action.setCallback(this, function(response){
            component.set("v.case_status", response.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})

Apex 控制器:GuestUserCreateForLater.cls

此示例 Apex 控制器接收用于创建和更新案例的调用。它使用用户加密解密 AppExchange 包来加密和解密数据。CreateCase()Apex 方法 使用来宾用户的输入创建案例。记录创建后,它 从记录 ID、记录字段和当前 时间戳。Apex 将新案例的 ID 替换为加密的 字符串。CreateCase()CreatedDateUpdateCase()该方法解密 提供的字符串,验证结果,并使用信息来 更新原始记录的状态。响应是 记录或错误消息(如果发生)。UpdateCase()

使用关键字定义类 因为它不直接访问记录。with sharing

警告

Internet 上的任何系统或个人都可以调用类。确保查询可以 仅更新正确的记录。@AuraEnabled

public with sharing class GuestUserCreateForLater {
    
    @AuraEnabled
    public static String CreateCase(String subject, 
                                         String description, 
                                         String email){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email);
        insert new_case;
        
       List<Case> results = GuestUserCaseHelperWS.getCase(new_case.Id);


        String encryptedID = ued.UserCryptoHelper.doEncrypt(results[0].Id+'|'+ results[0].CreatedDate.getTime() +'|'+System.DateTime.now().getTime());
        return encryptedID;
    }
    
    public static final Long validTimestampMinutes = 10;

    @AuraEnabled
    public static String UpdateCase(String token){
        String status = 'Case not found';
        String decrypted_token = '';
        try {
            decrypted_token = ued.UserCryptoHelper.doDecrypt(token);
        } catch(Exception e) {
            return status;
        }
        String[] decrypted_parts = decrypted_token.split('\\|');
        String decryptedRecordId = decrypted_parts[0];
        String created_timestamp = decrypted_parts[1];
        String original_request_timestamp = decrypted_parts[2];


        if( isTimestampValid(System.Long.valueOf(original_request_timestamp))) {

        	List<Case> caseList = GuestUserCaseHelperWS.getCase(decryptedRecordId, created_timestamp);
            if(caseList.size() == 1){
    	       Case case_to_update = caseList[0];
                        case_to_update.Status = 'Closed';
                try {
                         GuestUserCaseHelperWS.updateCase(case_to_update);
                         status = 'Closed';
                } catch(DmlException e){
                         System.debug('An unexpected error has occurred: ' + e.getMessage());
                }
            }else{
                status = 'Case not found';
            }
        }
        return status;
    }

    private static Boolean isTimestampValid(Long timestamp)
    {
        return ((System.now().getTime() - timestamp) / 60000) < validTimestampMinutes;
    }
}

Apex 帮助程序类:GuestUserCaseHelperWS.apxc

此示例 Apex 帮助程序类定义按记录的 ID 和 更新记录。Apex 控制器调用此方法。

使用关键字定义类,以便它可以检索和更新记录,而无需共享。without sharing

public without sharing class GuestUserCaseHelperWS {

    public static List<Case> getCase(String caseID, Datetime created_date)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate, Case.Status  
        FROM Case 
        WHERE Case.Id=:caseIDAND Case.CreatedDate=:created_date];
        return results;
    }

    public static Case updateCase(Case case_to_update)
    {
        update case_to_update;
        return case_to_update;
    }
}

限制对 Apex 类的访问

仅允许来宾和外部用户访问他们必须访问的类 叫。

如果 Apex 类包含公开的方法,例如使用 、、 或 的方法,则来宾和外部用户可以调用这些方法 具有任意参数的方法。但是他们必须具有执行 Apex 类的权限。我们 建议将 Apex 类访问权限限制为具有特定权限集或配置文件的用户。 允许来宾和外部用户对 Apex 类的完全访问权限是不安全的。㥢 关于哪些用户必须调用哪些 Apex 类,为这些角色创建权限集,以及 为所需的权限集启用 Apex 类。@InvocableMethod@AuraEnabled@RestResourcewebservice

流量安全

如果来宾用户或外部用户必须运行流,请覆盖流权限以授予访问权限 仅适用于特定的外部用户配置文件、权限集或站点来宾用户配置文件,而不是 而不是允许用户运行所有流。尽可能避免在系统上下文中运行流,以及 限制对子流的访问。否则,请确保对 这些流和子流。

流是一项强大的功能,可以覆盖平台安全设置以访问 对象和 Apex 类。流可用于激活和停用权限集。还 屏幕流由浏览器使用用户控制的输入参数驱动。因此,我们 建议重写“运行流”权限以将访问权限分配给 基于来宾或外部用户配置文件或权限集的特定流。对于来宾用户, 在相应站点的来宾用户配置文件上配置流访问策略。

删除运行子流的权限也是一种很好的安全做法,即使用户运行 子流独立。从安全角度来看,最好创建两个单独的 流,并仅授予对用户直接运行的流的访问权限,而不授予对以 子流。仅向最高级别的父流授予流访问权限,而不向子流授予流访问权限。 同样的建议也适用于流调用的可调用的 Apex 方法。避免授予 用户对这些类的访问权限,因此调用这些方法仅限于 他们注定要被召唤。请注意,如果用户有权运行屏幕流,他们可以:

  • 随时使用他们选择的参数调用流。
  • 随时取消流。

这些注意事项也适用于子流或从其他流调用的流。具体而言,流用户可以:

  • 查看和修改屏幕流的输入(开始)变量。
  • 查看从屏幕子流返回到父流的输出变量。
  • 如果他们有权运行子流,请将输入变量修改为子流。

如果其中任何一项功能违反了您的安全策略,请不要使用子流。例如,如果 处理必须保密的账单信息或其他敏感信息 通过子流。将业务逻辑保留在主流中。

SOQL注射液

清理传递到动态 SOQL 查询的用户控制数据。当 Apex 代码将用户控制的数据插入到动态 SOQL 中时,会发生 SOQL 或 SOSL 注入 或 SOSL 查询,但未正确审查输入。有两种情况需要考虑:

  • 更改查询的整体结构
  • 更改查询参数的值

通过调用阻止调用方访问数据的 Apex 代码来控制这些方案 他们无权获得。考虑一下 法典:

@AuraEnabled
public static List<Account> getAccountName(string userId) {
  if (FeatureManagement.checkPermission('readAccount')) {
      string query='SELECT Name FROM Account WHERE Id=\''+ userId + '\'';
      return database.query(query);
  }
}

用户可能会获得对查询的控制权,并访问比他们更多的信息 有权。查询的返回值不会限制用户可以访问的信息。用户可以 提交字符串,例如 :

userId = '0035Y00003pPJiNQAW\' OR AnnualRevenue>100000.00 OR Name=\'a'
// 0035Y00003pPJiNQAW is any id to any object that is not an account

这 查询的返回值将列出年收入超过 100,000 美元的所有帐户, 这不是开发人员打算返回给调用方的内容。修复 SOQL 或 SOSL 注入需要适当的上下文编码。不适用于每个用户输入。而 根据字段在 SOQL 或 SOSL 查询中的显示位置清理字段。

String.escapeSingleQuotes

  • 对于 WHERE (SOQL)、ORDER BY (SOQL)、WITH (SOSL) 或 FIND (SOSL) 子句中的变量,请使用 绑定 变量:string query='SELECT Name FROM Account WHERE Id=:userId';
  • 对于字段和表名称,请调用字段的 。或强制执行 声明性策略,使用您自己的过程逻辑将字段或表名限制为 您的安全策略允许的内容。isAccessibledescribeResult
  • 对于带引号的字符串中的参数,请使用绑定变量。不要使用绑定变量或清理表名 和字段名称,或未出现在引号上下文中的任何参数。String.escapeSingleQuote
  • 对于其他基元类型,将用户输入转换为布尔值、整数、Id 或其他 基元(非字符串)类型。

请注意,WITH SECURITY_ENFORCED关键字不会清理 WHERE 子句,只会清理 WHERE 子句 SELECT 和 FROM 子句,因此它不是 SOQL 或 SOSL 注入攻击的清理程序。

自定义模板的主题布局

若要将自己的图章放在模板主题上并转换其外观,请构建自定义 主题布局组件。您可以自定义模板的结构布局,例如标题 和页脚,并覆盖其默认样式。

主题布局组件是模板的顶级布局 (1) 网站中的页面。主题布局组件通过以下方式组织并应用于您的页面 主题布局。主题布局组件包括通用页眉和页脚 (2),并且通常 包括导航、搜索和用户配置文件菜单。相比之下,内容布局 (3) 定义页面的内容区域。下图显示了两列内容 布局。

自定义主题布局如何工作?

要了解主题布局的工作原理,让我们看看体验中的内容 构建器透视图。在Experience Builder中,主题布局与主题布局组件相结合 让您精细控制网站中每个页面的外观和结构。您可以 自定义布局的页眉和页脚以匹配您公司的品牌和风格,配置 主题属性,或使用自定义搜索栏和用户配置文件菜单。然后,使用主题布局 将主题布局组件应用于单个页面并快速更改一个页面的布局 中心位置。主题布局对网站中共享相同主题布局的页面进行分类 元件。您可以将主题布局组件分配给任何现有主题布局。然后你 在页面的 性能。

例如,Customer Service 模板包括以下主题 布局和组件,但您可以创建自定义组件或将布局切换为 需要。

  • 默认将 Customer Service 主题布局应用于除登录名之外的所有页面 页面。
  • 登录管理器将登录正文布局主题布局组件应用于登录页面。

假设您为即将到来的春季广告系列创建了三个页面。使用该界面,您可以创建一个 开发者控制台中的自定义大标题主题布局。在“设置”|”主题区域中,您可以添加一个名为 Spring 的自定义主题布局来对广告系列进行分类 页面,然后将“大页眉布局”组件分配给它。forceCommunity:themeLayout

接下来,在每个页面的属性中应用 Spring 主题布局,这会立即 将“大页眉”布局应用于每个页面。选择覆盖默认主题 此页面的布局。(1) 显示主题布局。选择新布局 (2) 从可用的选项中。

一切看起来 玫瑰色直到副总裁 营销部门认为标题占用了太多空间。这很容易解决,因为你 无需更新每个页面的属性即可更改主题布局。取而代之的是,使用 在主题区域一键切换,即可将 Spring 切换到 Small Header 布局,并立即 更新所有三个页面。

现在,假设“小标题”布局包括两个自定义属性:蓝色 背景和小标志。您已启用这些属性并将其应用于所有广告系列 页面。但是,对于一个页面,您只想应用 Small Logo 属性。

在这种情况下,您可以创建一个名为 Spring B 的主题布局,分配 Small Header layout 组件,并启用 Small Logo。然后,将 Spring B 主题应用于 页。

不确定哪些页面与您的任何主题布局相关联?

只需单击并一目了然,您就可以看到有多少个页面以及与其中任何一个页面相关联 您的主题布局。从“设置”|”主题,单击任何主题布局行 (1) 的“分配的页面总数”。单击此按钮 value 打开与该主题布局关联的页面列表 (2)。

主题布局可以很容易地以不同的方式重用相同的主题布局组件,而 根据需要保持尽可能多的精细控制。

配置自定义主题布局组件

让我们看看如何在开发者控制台中创建自定义主题布局组件,以 转换 Customer Service 中页面的外观和整体结构 模板。

1. 将界面添加到您的主题布局 元件

主题布局组件必须实现界面才能显示在Experience Builder的“设置”|”主题面积。forceCommunity:themeLayout

在代码中显式声明,以确保主题布局包含内容布局。添加您希望页面内容显示的任何位置 在主题布局中。{!v.body}{!v.body}

在主题布局中添加声明为包含区域的属性,这些属性包含 页面的组件。您可以将组件添加到标记中的区域,也可以保留区域 打开供用户拖放组件。声明为标记并包含在标记中的属性呈现为 在主题布局中打开用户可以向其添加组件的区域。为 例:Aura.Component[]Aura.Component[]

<aura:component implements="forceCommunity:themeLayout">
<aura:attribute name="myRegion" type="Aura.Component[]"/>

{!v.body}

</aura:component>

在 Customer Service 中,模板标题包括 这些锁定区域。

  • search,其中包含搜索发布服务器 元件
  • profileMenu,其中包含配置文件标头 元件
  • navBar,其中包含导航菜单 元件

创建重用模板中现有组件的自定义主题布局 标头区域,根据需要声明 、 或作为属性名称值。为 例:

searchprofileMenunavBar

<aura:attribute name="navBar" type="Aura.Component[]" required="false" />

提示

如果创建可交换的自定义配置文件菜单或搜索 组件,声明 or 属性名称值还允许用户选择 在Experience Builder中使用主题布局时的自定义组件。searchprofileMenu

将区域添加到标记 以定义在主题布局正文中显示它们的位置。下面是 一个简单的主题 布局。

<aura:component implements="forceCommunity:themeLayout" access="global" description="Sample Custom Theme Layout">
    <aura:attribute name="search" type="Aura.Component[]" required="false"/>
    <aura:attribute name="profileMenu" type="Aura.Component[]" required="false"/>
    <aura:attribute name="navBar" type="Aura.Component[]" required="false"/>
    <aura:attribute name="newHeader" type="Aura.Component[]" required="false"/>
    <div>
        <div class="searchRegion">
            {!v.search}
        </div>
        <div class="profileMenuRegion">
            {!v.profileMenu}
        </div>
        <div class="navigation">
            {!v.navBar}
        </div>
        <div class="newHeader">
            {!v.newHeader}
        </div>
        <div class="mainContentArea">
            {!v.body}
        </div>
    </div>
</aura:component>

2. 添加设计资源以包含主题属性

您可以在Experience Builder中公开主题布局属性,方法是添加 将资源设计到您的捆绑包中。

首先,在组件中实现属性。

<aura:component implements="forceCommunity:themeLayout" access="global" description="Small Header">
    <aura:attribute name="blueBackground" type="Boolean" default="false"/> 
    <aura:attribute name="smallLogo" type="Boolean" default="false" />
    ...

在设计资源中定义主题属性,以在 UI 中公开这些属性。本示例为 Small 添加标签 标题主题布局以及两个复选框。

<design:component label="Small Header">
    <design:attribute name="blueBackground" label="Blue Background"/>
    <design:attribute name="smallLogo" label="Small Logo"/>
</design:component>

3. 添加 CSS 资源以避免重叠问题

将 CSS 资源添加到捆绑包中,以根据需要设置主题布局的样式,最好使用标准设计标记。

要避免与定位元素(如对话框或悬停器)出现重叠问题,请执行以下操作:

  • 应用 CSS 样式。.THIS { position: relative; z-index: 1; }
  • 将自定义主题布局中的元素包装在标签中。div<div class="mainContentArea"> {!v.body} </div>

注意

主题布局控制其中任何内容的样式,因此它可以添加样式,例如 作为区域或组件的投影。对于自定义主题布局,SLDS 由 违约。

使用表达式向 Aura 站点添加动态数据

使用表达式,您可以访问属性值和其他信息以传递到 组件的属性。

表达式是任何一组文本值、变量、子表达式或运算符,它们 可以解析为单个值。表达式中不允许进行方法调用。

表达式语法为: 其中 是表达式的占位符。{!expression}expression

使用这些表达式可显示经过身份验证的用户的信息、关联的图像 具有数据类别,或在网站页面上记录信息。

表达显示
{!CurrentUser.name}组合用户的名字和姓氏,如用户详细信息上所示 页。
{!CurrentUser.firstName}用户的名字,如用户编辑页面上所示。
{!CurrentUser.lastName}用户的姓氏,如用户编辑页面上所示。
{!CurrentUser.userName}定义用户登录名的管理字段。
{!CurrentUser.id}用户的 Salesforce ID。
{!CurrentUser.email}用户的电子邮件地址。
{!CurrentUser.communityNickname}用于标识网站中用户的名称。
{!CurrentUser.accountId}与用户关联的帐户 ID。此表达式显示有效帐户 合作伙伴和客户用户的 ID。对于所有其他内容,它显示 ‘000000000000000’.
{!CurrentUser.effectiveAccountId}与有效账户关联的账户 ID。此表达式显示 合作伙伴和客户用户的有效帐户 ID。对于所有其他内容,它显示 ‘000000000000000’.
{!Global.PathPrefix}/{!DataCategory.Name}.jpg与搜索组件中的数据类别关联的图像。
{!Global.PathPrefix}/<Name of the Subfolder>/{!DataCategory.Name}.jpg与搜索中的子文件夹中的数据类别关联的图像 元件。
{!recordId}对象页面上的 15 位记录 ID。
{!term}在基于 Aura 的标准中返回 HTML 编码的搜索词的表达式 搜索页面。

为 Experience Builder 创建自定义内容布局组件

Experience Builder 包含多个定义内容的即用型布局 页面的区域,例如比例为 2:1 的两列布局。但是,如果您需要 为您的网站自定义的布局,请创建自定义内容布局组件以在以下情况下使用 在Experience Builder中构建新页面。您还可以更新默认的内容布局 网站模板附带的页面。

当您在开发者控制台中创建自定义内容布局组件时,它会 显示在 Experience Builder 的 “新建页面”和“更改布局”对话框。

1. 向内容布局组件添加新界面

要显示在Experience Builder的“新建页面”和“更改布局”对话框中,请 内容布局组件必须实现接口。forceCommunity:layout下面是一个简单的两列内容的示例代码 布局。

<aura:component implements="forceCommunity:layout" description=”Custom Content Layout” access="global">
    <aura:attribute name="column1" type="Aura.Component[]" required="false"></aura:attribute>
    <aura:attribute name="column2" type="Aura.Component[]" required="false"></aura:attribute>

    <div class="container">
        <div class="contentPanel">
            <div class="left">
                {!v.column1}
            </div>
            <div class="right">
                {!v.column2}
            </div>
        </div>
    </div>
</aura:component>

注意

标记您的资源,例如 一个组件,用 可在您自己的组织外部使用的资源。access=”global”例如,如果您想要一个组件 可在已安装的软件包中使用,或由 Lightning 应用程序构建器用户或 其他组织中的 Experience Builder 用户。

您还可以为 标记为 的组件、事件或接口。本文档会自动显示在 使用或安装包的组织的组件库。access=”global”

2. 将 CSS 资源添加到组件包中

接下来,添加一个 CSS 资源来设置 根据需要进行内容布局。

下面是我们简单的两列内容布局的示例 CSS。

.THIS .contentPanel:before,
.THIS .contentPanel:after {
    content: " ";
    display: table;
}
.THIS .contentPanel:after {
    clear: both;
}
.THIS .left {
    float: left;
    width: 50%;
}
.THIS .right {
    float: right;
    width: 50%;
}

CSS 资源必须命名为 componentName.css

3. 可选:将 SVG 资源添加到组件包

您可以在 组件包,用于定义内容布局组件出现在 体验生成器。

Experience Builder 中内容布局组件的建议图像大小为 170px 按 170px。但是,如果图像具有不同的尺寸,则 Experience Builder 会进行缩放 要适合的图像。

SVG 资源必须命名为 componentName.svg

配置可交换搜索和配置文件菜单组件

创建自定义组件以替换模板的标准配置文件标题和搜索 & Experience Builder 中的 Post Publisher 组件。

例如,在 Customer Service 中,模板标题由这些锁定的 地区:

  • search,其中包含搜索发布服务器 元件
  • profileMenu,其中包含配置文件标头 元件
  • navBar,其中包含导航菜单 元件

通过这些指定的区域名称,您可以轻松地:

  • 在默认主题布局组件或自定义组件中交换搜索和配置文件组件 主题布局组件。
  • 交换主题布局组件,同时保留现有自定义项,例如 选定的搜索组件。

当组件实现正确的接口(在本例中为 )时,它将被标识为候选接口 对于这些地区。因此,它们在主题布局中显示为可交换组件 组件,例如默认的 Customer Service 主题布局组件,该组件声明 或 作为属性名称 价值。

forceCommunity:searchInterfaceforceCommunity:profileMenuInterfacesearchprofileMenu

<aura:attribute name="search" type="Aura.Component[]" required="false" />

forceCommunity:profileMenuInterface

添加接口 添加到 Aura 组件中,以允许将其用作 模板。创建自定义配置文件菜单组件后,管理员可以在Experience Builder的“设置”|”主题以替换模板的标准配置文件标头组件。forceCommunity:profileMenuInterface

此代码适用于简单的配置文件菜单组件。

<aura:component implements="forceCommunity:profileMenuInterface" access="global">
    <aura:attribute name="options" type="String[]" default="Option 1, Option 2"/>
    <ui:menu >
        <ui:menuTriggerLink aura:id="trigger" label="Profile Menu"/>
        <ui:menuList class="actionMenu" aura:id="actionMenu">
            <aura:iteration items="{!v.options}" var="itemLabel">
                <ui:actionMenuItem label="{!itemLabel}" click="{!c.handleClick}"/>
            </aura:iteration>
        </ui:menuList>
    </ui:menu>
</aura:component>

forceCommunity:搜索接口

将接口添加到 Aura 组件,允许将其用作模板的自定义搜索组件。后 您创建自定义搜索组件,管理员可以在Experience Builder的“设置”|”主题替换模板的标准 Search & Post Publisher 组件。forceCommunity:searchInterface

此代码适用于简单的搜索组件。

<aura:component implements="forceCommunity:searchInterface" access="global">
    <div class="search">
        <div class="search-wrapper">
            <form class="search-form">
                <div class="search-input-wrapper">
                    <input class="search-input" type="text" placeholder="My Search"/>
                </div>
                <input type="hidden" name="language" value="en" />
            </form>
        </div>
    </div>
</aura:component>

Experience Builder 站点的标准设计令牌

Salesforce 公开了一组基本令牌,您可以在组件样式中访问这些令牌 资源。您可以使用这些标准令牌来模仿 Salesforce 的外观 Lightning Design System (SLDS) 在您自己的自定义组件中。随着 SLDS 的发展,组件 使用标准设计令牌进行样式设置的令牌也随之发展。使用 标准设计令牌,使您的组件与体验中的“主题”面板兼容 建筑工人。

通过“主题”面板,管理员可以使用品牌快速设置整个网站的样式 性能。“主题”面板中的每个属性都映射到一个或多个标准设计标记。 当管理员更新“主题”面板中的属性时,系统会更新 使用与该属性关联的令牌的 Lightning 组件。

Experience Builder 站点的可用令牌

对于Experience Builder站点,扩展时可以使用以下标准令牌 来自 force:base

重要

标准令牌值随着 SLDS 的发展而变化。可用的令牌和 它们的值可能会更改,恕不另行通知。

这些“主题”面板属性……映射到这些标准设计令牌
文本颜色colorTextDefault
详细文本颜色colorTextActionLabel
动作颜色colorBackgroundButtonBrandcolorBorderBrandcolorBorderButtonBrandcolorBrandcolorTextBrandcolorTextActionLabelActivecolorTextTabLabelSelected注意从 Summer ’18 开始,不再映射到 Action Color。colorBackgroundHighlight
链接颜色colorTextLink
公司 LogobrandLogoImage
叠加文本颜色colorTextButtonBrandcolorTextButtonBrandHovercolorTextInverse
边框颜色colorBordercolorBorderButtonDefaultcolorBorderInputcolorBorderSeparatorAlt
主字体fontFamily
文本大小写textTransform

此外,以下标准令牌可用于 模板。在更新 “主题”面板中的属性。例如,如果更改 主题面板中,系统会根据新的 价值。

这些派生的品牌属性……映射到这些标准设计令牌
动作颜色更暗(源自 Action Color)colorBackgroundButtonBrandActivecolorBackgroundButtonBrandHover
悬停颜色(源自 Action Color)colorBackgroundButtonDefaultHovercolorBackgroundRowHovercolorBackgroundRowSelectedcolorBackgroundShade
链接颜色较深(源自 Link Color)colorTextLinkActivecolorTextLinkHover

有关 SLDS 中可用的设计令牌的完整列表,请参阅 Lightning Design 上的设计令牌 系统站点。

注意

一些开箱即用的组件不使用标准设计令牌。因此,如果你 使用标记 在设置主题布局样式时,某些组件可能不会继承 定义。

确保具有 Experience Cloud 站点的组织中的自定义组件是安全的

开发人员可以通过以下方式自定义 Experience Cloud 站点中的功能和业务逻辑 使用自定义组件。与任何自定义解决方案一样,开发人员必须意识到潜力 与安全相关的陷阱。绕过内置防御措施可以使站点和组织暴露在安全之下 风险。

例如,如果开发人员在自定义组件的定义中将敏感数据存储为文本, 数据可能会暴露。当数字体验 在组织中启用,组织具有自定义组件,并且自定义组件的开发人员名称为 已知。无论网站是公共的还是私有的,都可能发生暴露。

公开的数据可以包括:

  • 在组件定义中存储为文本的敏感信息
  • 组件的完整组件定义,包括 HTML、JavaScript 和 CSS 文件
  • 组件定义中包含的任何其他组件的名称
  • 组件定义中使用的任何 Apex 控制器和方法名称

此类数据可以针对组织中的任何自定义组件公开,无论它们是否用于 Salesforce 组织、Experience Cloud 站点上或未使用时。请执行以下步骤来降低自定义组件中数据泄露的风险。

  • 查看组织中所有自定义组件中的组件定义
  • 避免在组件定义中存储任何敏感数据。敏感数据可以包括 个人身份信息、公司机密信息或任何信息 被视为对您的业务和客户敏感
  • 查看所有自定义控制器,并确保只有必需的用户配置文件具有访问权限 对他们来说
  • 确保使用@AuraEnabled
  • 对组织复杂且唯一的自定义组件使用命名约定

自定义体验生成器模板的外观

您可以通过多种方式控制 Experience Builder 模板的外观,每种方式 具有不同的复杂性和粒度。

在Experience Builder中,您可以修改特定于模板的样式,以及 因此,不能在站点之间共享。Experience Builder 中的选项是最简单的 使用并且不需要编码。

  • “主题”面板使用简单的 点击属性。此方法非常适合管理员使用。注意个人 组件属性面板(例如标题或搜索)提供了其他更多功能 外观和感觉的具体调整。
  • CSS 编辑器允许您创建自定义 CSS,以覆盖 模板元素的基本样式。如果您熟悉 CSS 和 只想对一些开箱即用的组件或模板进行微小的修改 元素。注意随着主题交换的引入,您输入的任何自定义 CSS 现在直接绑定到您的活动主题。对于现有站点,请确保任何所需的 您当前可能使用的自定义 CSS 将复制到新选择的主题中。哪里 自定义 CSS 是必需的,请在主题中使用 Experience Builder 站点的设计令牌 有意义的布局(、等)以减轻未来的痛苦 更新了模板和主题。brandLogoImageaction color

但是,要完全自定义模板的外观,您需要构建自己的模板 组件。

  • 习惯 Aura 组件将 CSS 资源封装为 组件包,使组件可跨站点重用。
  • 内容布局组件定义 页面并包含组件。
  • 主题布局组件可让您自定义结构 模板的布局,例如页眉和页脚,并覆盖其默认值 风格。
  • 使用“主题”面板
    更新模板 在Experience Builder中,更改模板外观的最简单方法是使用“主题”面板。管理员可以使用主题面板快速设置整个网站的样式,以应用颜色、指定字体、添加徽标或调整常规页面结构和默认值。
  • 使用自定义 CSS 覆盖模板元素 使用 Experience Builder 中的 CSS 编辑器添加自定义 CSS
    ,以覆盖默认模板和主题面板样式。您还可以使用它对开箱即用组件的外观进行细微更改,例如填充调整。
  • 在Experience Builder站点中使用自定义字体 将自定义字体作为静态资源上传,并将其用于整个站点
    的主要字体和标题字体。如果要上传多个字体文件,请使用 .zip 文件。
  • 自定义模板的主题布局 若要在模板
    主题上放置自己的图章并转换其外观,请构建自定义主题布局组件。您可以自定义模板的结构布局(如页眉和页脚),并覆盖其默认样式。
  • 使用表达式向 Aura 站点
    添加动态数据 使用表达式,您可以访问属性值和其他信息以传递到组件的属性中。
  • 为 Experience Builder
    创建自定义内容布局组件 Experience Builder 包含多个现成的布局,用于定义页面的内容区域,例如比例为 2:1 的两列布局。但是,如果您需要为站点自定义的布局,请创建自定义内容布局组件,以便在Experience Builder中构建新页面时使用。您还可以更新网站模板附带的默认页面的内容布局。
  • 配置可交换的搜索和用户档案菜单组件
    在Experience Builder中创建自定义组件以替换模板的标准用户档案标题和搜索和发布发布者组件。
  • Experience Builder Sites
    Salesforce 的标准设计令牌公开了一组基本令牌,您可以在组件样式资源中访问这些令牌。您可以使用这些标准令牌在您自己的自定义组件中模拟 Salesforce Lightning Design System (SLDS) 的外观。随着 SLDS 的发展,使用标准设计标记设置样式的组件也随之发展。使用标准设计令牌的子集,使您的组件与Experience Builder中的主题面板兼容。
  • 确保具有 Experience Cloud 站点的组织中的自定义组件是安全的
    开发人员可以使用自定义组件自定义 Experience Cloud 站点中的功能和业务逻辑。与任何自定义解决方案一样,开发人员必须意识到与安全相关的潜在陷阱。绕过内置防御可能会使站点和组织面临安全风险。

使用“主题”面板更新模板

在Experience Builder中,更改模板外观的最简单方法是使用 “主题”面板。管理员可以使用主题面板快速设置整个网站的样式,以 应用颜色、指定字体、添加徽标或调整常规页面结构和 违约。

在“主题”面板中设置的属性适用于模板中的页面,并且大多数 现成的组件。使用品牌集快速应用颜色、图像和 字体。

“主题”面板的属性也适用于使用标准设计标记来控制其外观的自定义 Lightning 组件。

注意

如果您仍在使用 Spring ’17 的模板,要统一 使用网站其余页面登录页面,在“设置”|”更新。否则,您必须单独设置登录页面的主题。

使用自定义 CSS 覆盖模板元素

使用 Experience Builder 中的 CSS 编辑器添加自定义 CSS,以覆盖默认 模板和主题面板样式。您还可以使用它对外观进行细微更改 开箱即用的组件,例如填充调整。

重要

谨慎使用自定义 CSS。模板组件的未来版本可能会 不支持您的 CSS 自定义。此外,Salesforce 客户支持也无能为力 解决自定义 CSS 的任何问题。

提示

对于实质性的模板自定义,请使用 自定义 Lightning Web 组件或 Aura 组件和自定义主题中的 CSS 资源 布局组件。如果您使用全局覆盖,请始终在沙盒中测试您的网站,当它处于 更新了每个版本。

要对模板项进行细微的 CSS 修改,请使用 Chrome DevTools 检查页面 并发现项目的完全限定名称和 CSS 类。然后使用该信息 使用自定义 CSS 覆盖项目的标准 CSS。要了解有关检查和 编辑页面和样式,请参阅 Google Chrome 的 DevTools 网站。检查组件的最简单方法是在预览模式下查看页面。这个例子 检查 Headline 组件以找到组件的完全限定名称 – 。

forceCommunityHeadline

注意

如果顶级 CSS 类不是 为组件定义时,此选项不会显示,这意味着您不能可靠地 以组件为目标。

然后找到要设置样式的元素,例如 .如果元素没有类名,则必须编写 针对元素的特定选择器。headlineTitleText

使用该信息,您可以创建自定义样式以覆盖默认标题 颜色。

.forceCommunityHeadline .headlineTitleText
{
    color: red;
}

然后将其添加到CSS编辑器中。同样,您可以使用自定义 CSS 来隐藏组件 完全。

.forceCommunityHeadline
{
    display: none;
}

提示

您可以将 CSS 样式表作为静态或外部资源链接到 “设置”|”高级。但是,由于 head 标记中不支持全局值提供程序 或者在 CSS 覆盖中,你不能使用 引用静态资源。请改用语法 /sfsites/c/resource/resource_name 的相对 URL。$resource为 例如,如果您将图像作为名为 Headline 的静态资源上传,请在 CSS 编辑器作为 遵循:

.forceCommunityHeadline
{
    background-image: url('/sfsites/c/resource/headline')
}

头 标记对于添加图标、SEO 元标记和其他项目也很有用。然而 请注意,使用默认的严格 CSP 安全级别可能会影响代码。

  • 迁移 CSS 覆盖
    在 17 年春季和 19 年冬季之间,更新了多个 Experience Builder 组件的 CSS 选择器。如果您此后没有更新模板,并且您的网站使用自定义 CSS 来覆盖默认模板和主题面板样式,则必须迁移到新的选择器。

迁移 CSS 覆盖

在 17 年春季和 19 年冬季之间,多个 Experience Builder 的 CSS 选择器 组件已更新。如果您此后没有更新模板,并且您的网站使用 自定义 CSS 要覆盖默认模板和主题面板样式,您必须迁移到新的 选择。

请参阅更新体验生成器 Salesforce 帮助中的模板。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。
  • 导航菜单
    的 CSS 覆盖迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖面板容器
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录横幅组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录详细信息组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录布局组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录列表组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录相关列表组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖相关文章组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • 信誉排行榜组件
    的 CSS 覆盖迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖嵌入式服务侧边栏标头组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖按主题组件
    分类的热门文章的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。

CSS 覆盖导航菜单的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题介绍导航菜单的选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整导航菜单

上一个选择器新选择器
.forceCommunityNavigationMenu.forceCommunityNavigationMenu #navigationMenu.forceCommunityNavigationMenu .navigationMenu.forceCommunityNavigationMenu .navigationMenuWrapper.comm-navigation

移动菜单窗帘

上一个选择器新选择器
.forceCommunityNavigationMenu .navigationMenuWrapperCurtain.comm-navigation nav.slds-is-fixed

主菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .homeLink.forceCommunityNavigationMenu .homeButton.comm-navigation .slds-list__item a[data-type=”home”]

主菜单项链接

上一页 选择器新选择器
.forceCommunityNavigationMenu.homeLink.forceCommunityNavigationMenu.homeButton.comm-navigation .slds-list__item a[data-type=”home”].comm-navigation .comm-navigation__item a[data-type=”home”]

移动菜单切换按钮

上一个选择器新选择器
.forceCommunityNavigationMenu .toggleNav.siteforceServiceBody .cHeaderPanel .cAltToggleNav

顶级菜单项

包括子菜单触发器。

上一个选择器新选择器
.forceCommunityNavigationMenu .menuItem.forceCommunityGlobalNavigation .navigationMenuNode.comm-navigation .comm-navigation__list > .slds-list__item
.forceCommunityNavigationMenu .menuItem.forceCommunityGlobalNavigation .navigationMenuNode.comm-navigation .comm-navigation__list > .slds-list__item.comm-navigation .comm-navigation__list > .slds-list__item > .comm-navigation__item

当前顶级菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .current.forceCommunityGlobalNavigation .menuItem.current.comm-navigation .comm-navigation__list > .slds-list__item > .slds-is-active
.forceCommunityNavigationMenu .current.forceCommunityGlobalNavigation .menuItem.current.comm-navigation .comm-navigation__list > .slds-list__item > .slds-is-active.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > .slds-is-active

顶级菜单项链接

上一个选择器新选择器
.forceCommunityNavigationMenu .menuItemLink.forceCommunityNavigationMenu a.menuItemLink.forceCommunityNavigationMenu .menuItem .menuItemLink.forceCommunityNavigationMenu .menuItem a.forceCommunityNavigationMenu .menuItem a.menuItemLink.comm-navigation .comm-navigation__list > .slds-list__item > a.comm-navigation .comm-navigation__list > .slds-list__item > button
.forceCommunityNavigationMenu .menuItemLink.forceCommunityNavigationMenu a.menuItemLink.forceCommunityNavigationMenu .menuItem .menuItemLink.forceCommunityNavigationMenu .menuItem a.forceCommunityNavigationMenu .menuItem a.menuItemLink.comm-navigation .comm-navigation__list > .slds-list__item > a.comm-navigation .comm-navigation__list > .slds-list__item > button.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > a.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > button

子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item

当前/活动子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.current.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item .slds-is-active
.forceCommunityNavigationMenu .subMenuItem.current.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item .slds-is-active.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item .slds-is-active

子菜单触发链接

上一个选择器新选择器
.forceCommunityNavigationMenu .triggerLink.forceCommunityNavigationMenu .triggerLabel.comm-navigation .slds-list__item button:enabled
.forceCommunityNavigationMenu .triggerLink..forceCommunityNavigationMenu .triggerLabel.comm-navigation .slds-list__item button:enabled.comm-navigation .comm-navigation__item button:enabled

子菜单触发链接图标

上一个选择器新选择器
.forceCommunityNavigationMenu .triggerLink .forceIcon.comm-navigation .slds-list__item button:enabled .slds-icon_container
.forceCommunityNavigationMenu .triggerLink .forceIcon.comm-navigation .slds-list__item button:enabled .slds-icon_container.comm-navigation .comm-navigation__item button:enabled .slds-icon_container

菜单项

包括顶级菜单项和子菜单项。

上一个选择器新选择器
.forceCommunityNavigationMenu .navigationMenu li.comm-navigation .slds-list__item
.forceCommunityNavigationMenu .navigationMenu li.comm-navigation .slds-list__item.comm-navigation .comm-navigation__item

菜单项链接

包括顶级菜单项和子菜单项。

上一个选择器新选择器
.forceCommunityNavigationMenu a.forceCommunityNavigationMenu a.menuItemLink.comm-navigation .slds-list__item a.comm-navigation .slds-list__item button
.forceCommunityNavigationMenu a.forceCommunityNavigationMenu a.menuItemLink.comm-navigation .slds-list__item a.comm-navigation .slds-list__item button.comm-navigation .comm-navigation__item a.comm-navigation .comm-navigation__item button

子菜单

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenu.comm-navigation .slds-list_vertical.slds-is-nested

子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item

子菜单项链接

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem a.forceCommunityNavigationMenu .subMenu a.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item a
.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item a

CSS 覆盖 Panels 容器的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

面板容器

上一个选择器新选择器
.uiPanelManager2.onePanelManager.siteforcePanelManager.comm-panels-container

CSS 覆盖记录横幅组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

详细字段标签

上一个选择器新选择器
.forceCommunityRecordHeadline .slds-text-heading-label-normal.forceCommunityRecordHeadline .slds-form-element__label

详细信息字段值

上一个选择器新选择器
.forceCommunityRecordHeadline .slds-text-body–regular.forceCommunityRecordHeadline .slds-form-element__static

CSS 覆盖记录详细信息组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

表单元素分隔符

上一个选择器新选择器
.forceCommunityRecordDetail .slds-form-element__control .slds-form-element_separator.forceCommunityRecordDetail .slds-form-element_separator

CSS 覆盖记录布局组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

全记录布局

上一个选择器新选择器
.forceRecordLayout.forceRecordLayout.forcePageBlockforce-record-layout2force-record-layout-block

部分

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSectionView.forceRecordLayout .full.forcePageBlockSection.forceRecordLayout .full.forcePageBlockSectionView.forcePageBlockSection.forceRecordLayout .forcePageBlockSectionView.forceRecordLayout .forcePageBlockSection.forceRecordLayout .forcePageBlockSectionView.forcePageBlockSectionforce-record-layout2 force-record-layout-section

章节标题

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSection h3force-record-layout2 force-record-layout-section h3

节行

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSectionRow.forceRecordLayout .forcePageBlockSectionRowforce-record-layout2 force-record-layout-row

部分项目

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockItem.forcePageBlockItemView.forceRecordLayout .full.forcePageBlockItem.forceRecordLayout .full.forcePageBlockItemView.forceRecordLayout .forcePageBlockItem.forceRecordLayout .forcePageBlockItemView.forceRecordLayout .forcePageBlockItem.forcePageBlockItemViewforce-record-layout2 force-record-layout-item

部分项目标签

上一个选择器新选择器
.forceRecordLayout .slds-form-element__labelforce-record-layout2 .slds-form-element__label

节项目值

上一个选择器新选择器
.forceRecordLayout .itemBodyforce-record-layout2 .slds-form-element__static

部分项目值链接

上一个选择器新选择器
.forceRecordLayout aforce-record-layout2 a

CSS 覆盖记录列表组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

列表视图按钮栏

上一个选择器新选择器
.forceListViewManagerHeader .forceListViewManagerButtonBar.forceListViewManagerHeader force-list-view-manager-button-bar

列表视图按钮 栏按钮

上一个选择器新选择器
.forceListViewManagerHeader .forceListViewManagerButtonBar button.forceListViewManagerHeader force-list-view-manager-button-bar button

列表视图状态信息

上一个选择器新选择器
.forceListViewManagerHeader .test-listViewStatusInfo.forceListViewManagerHeader force-list-view-manager-status-info

选取器触发器链接

上一个选择器新选择器
.forceListViewManagerHeader .triggerLink.forceListViewManagerHeader .triggerLink .slds-button

CSS 覆盖与记录相关的列表组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

详细字段标签

上一个选择器新选择器
.forceCommunityRelatedRecords .slds-card__header-link .slds-text-heading–small.forceCommunityRelatedRecords .slds-card__header-title

CSS 覆盖相关文章组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整相关文章

上一个选择器新选择器
.selfServiceSimilarArticles.base-items.uiAbstractList.selfServiceBaseSimpleItems.comm-related-articles

组件标题

上一个选择器新选择器
.selfServiceSimilarArticles h2.selfServiceSimilarArticles .base-items-header.comm-related-articles h2

文章列表

上一个选择器新选择器
.selfServiceSimilarArticles ul.selfServiceSimilarArticles .base-items.comm-related-articles ul

文章列表项

上一个选择器新选择器
.selfServiceSimilarArticles .base-simple-item.comm-related-articles li
.selfServiceSimilarArticles .base-simple-item.comm-related-articles li.comm-related-articles .comm-related-articles__item

文章链接

上一个选择器新选择器
.selfServiceSimilarArticles .item-title.selfServiceSimilarArticles .item-title-link.comm-related-articles li a
.selfServiceSimilarArticles .item-title.selfServiceSimilarArticles .item-title-link.comm-related-articles li a.comm-related-articles .comm-related-articles__item a

CSS 覆盖信誉排行榜组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整声誉排行榜

上一个选择器新选择器
.forceCommunityReputationLeaderboard.leaderboard.comm-leaderboard

声誉排行榜行

上一个选择器新选择器
.forceCommunityReputationLeaderboardRow.comm-leaderboard li
.forceCommunityReputationLeaderboardRow.comm-leaderboard li.comm-leaderboard .comm-leaderboard__item

用户信息列

上一个选择器新选择器
.forceCommunityReputationLeaderboard .pointsAndLevels.forceCommunityReputationLeaderboard .userInfoCol.comm-leaderboard .slds-media__body

声望点数列

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationCol.comm-leaderboard__points-column

标题

上一个选择器新选择器
.forceCommunityReputationLeaderboard .title.comm-leaderboard h2

用户级别名称

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationLevelName.comm-leaderboard__level-name

用户信誉级别图像

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationLevelImage.comm-leaderboard .slds-media__body .slds-icon_small

用户中的用户名

上一个选择器新选择器
.forceCommunityReputationLeaderboard .userName.comm-leaderboard__user-name

用户中的用户照片

上一个选择器新选择器
.forceCommunityReputationLeaderboard .userPhoto.comm-leaderboard .slds-media__figure

信誉级别的用户点数

上一个选择器新选择器
.forceCommunityReputationLeaderboard reputationPointsNumber..comm-leaderboard__points

用户在声誉级别中点词

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationPointsWord..comm-leaderboard__points-word

CSS 覆盖嵌入式服务侧边栏标头组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

标题背景颜色

上一个选择器新选择器
.sidebarHeader { background-color: #aaa; }.embeddedServiceSidebar.sidebarHeader { background-color:#aaa; }

CSS 按主题组件覆盖热门文章的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整的热门文章

上一个选择器新选择器
.selfServiceTopicTrendingArticles.base-items.uiAbstractList.selfServiceBaseSimpleItems.comm-topic-trending-articles

组件标题

上一个选择器新选择器
.selfServiceTopicTrendingArticles h2.selfServiceTopicTrendingArticles .base-items-header.comm-topic-trending-articles h2

文章列表

上一个选择器新选择器
.selfServiceTopicTrendingArticles ul.selfServiceTopicTrendingArticles .base-items.comm-topic-trending-articles ul

文章列表项

上一个选择器新选择器
.selfServiceTopicTrendingArticles .base-simple-item.comm-topic-trending-articles li
.selfServiceTopicTrendingArticles .base-simple-item.comm-topic-trending-articles li.comm-topic-trending-articles .comm-topic-trending-articles__item

文章链接

上一个选择器新选择器
.selfServiceTopicTrendingArticles .item-title-link.selfServiceTopicTrendingArticles a.comm-topic-trending-articles li a
.selfServiceTopicTrendingArticles .item-title-link.selfServiceTopicTrendingArticles a.comm-topic-trending-articles li a.comm-topic-trending-articles .comm-topic-trending-articles__item a

在 Experience Builder 站点中使用自定义字体

将自定义字体作为静态资源上传,并将其用于主字体和标题字体 整个站点。如果要上传多个字体文件,请使用 .zip 文件。

  1. 在“设置”中,在“快速查找”框中输入“静态资源”,然后 选择静态资源
  2. 单击“新建”,上传文件,并为静态资源命名。 记下资源名称。如果您的网站有公共页面,请在“缓存”中选择“公共” 控制设置。如果您不公开字体资源,则页面将使用 浏览器的默认字体。
  3. 在 Experience Builder 中, 通过单击“主题”|” |编辑 CSS
  4. 使用 @font面 CSS 规则引用 上传的字体。为 例:@font-face { font-family: 'myFirstFont'; src: url('/myPartnerSite/s/sfsites/c/resource/MyFonts/bold/myFirstFont.woff') format('woff'); }注意format() 是一个可选提示,用于描述 URL 中引用的字体。
    • 要引用单个字体文件,请使用语法 /path_prefix/s/sfsites/c/resource/resource_name, 其中 是 URL 值,当您 创建了网站,例如 myPartnerSite。path_prefix例如,如果您上传一个名为 myFirstFont.woff 的文件,并且 将资源命名为 MyFonts,URL 为 /myPartnerSite/s/sfsites/c/resource/MyFonts。
    • 若要引用 .zip 文件中的文件,请包含文件夹结构,但省略 .zip 文件名。使用语法 /path_prefix/s/sfsites/c/resource/resource_name/font_folder/font_file。因此,如果您上传包含 bold/myFirstFont.woff 的 fonts.zip,并将资源命名为 MyFonts,则 URL 为 /myPartnerSite/s/sfsites/c/resource/MyFonts/bold/myFirstFont.woff。
  5. 在“主题”面板中,选择“字体”,选择“主要字体”或 “标题字体”下拉列表,然后单击“使用自定义字体”。
  6. 添加您在 CSS 编辑器中输入的字体系列名称(例如,)并保存更改。myFirstFont

Experience Cloud 开发人员指南

快速了解 Experience Builder 站点

Experience Builder 模板允许您创建品牌网站,让您的员工、 客户和合作伙伴可以建立联系。基于 Lightning 组件框架构建,Experience 构建器模板包括许多现成的功能和 Lightning 组件。但真正的 Lightning 组件框架的强大之处在于您可以开发自定义的 Lightning 组件 和功能,以满足您独特的业务需求,并彻底改变外观和感觉 您的网站。

从 Spring ’19(API 版本 45.0)开始,您可以使用两个 编程模型:Lightning Web 组件模型和原始 Aura 组件 型。Lightning Web 组件是使用 HTML 和现代构建的自定义 HTML 元素 JavaScript的。

提示

重命名为 Experience Cloud Spring ’21(API 版本 50.0)引入了一些新术语,了解起来可能很棘手 什么是什么。这是纲要。

Experience Builder 站点(以前称为 Lightning 社区)是您在 Experience Builder 中自定义的基于模板的站点。 随着 Lightning Web 运行时 (LWR) 的推出,我们为 even 添加了两个新术语 更清晰。

  • LWR 站点使用最新的基于 LWR 的模板构建,例如 构建您自己的 (LWR) 模板。LWR 站点只能与 Lightning Web 组件一起使用, 不是 Aura 组件。查看 LWR 网站获取体验 云。
  • Aura 网站是使用我们的原始模板构建的,例如客户 服务、合作伙伴中心和客户帐户门户,在 Aura 上运行。对于光环 站点、Lightning Web 组件和 Aura 组件可以在 页。

您可以将 Lightning Web 组件和 Aura 组件配置为拖放式 Experience Builder 的组件。管理员和最终用户不知道哪种编程模型 用于开发组件 – 对他们来说,它们只是 Lightning 组件。

无论你是开发人员、合作伙伴还是 ISV,本指南都介绍了如何创建自定义 Aura 网站和组件、主题布局组件和 Lightning Bolt 解决方案。

  • 开始之前 在开始
    开发自定义 Experience Builder 站点之前,请确保您熟悉如何在 Lightning 中进行开发。
  • 什么是 Salesforce Lightning?
    借助 Salesforce Lightning,您可以更轻松地为任何设备构建响应式应用程序,并包含 Lightning 组件框架和面向开发人员的有用工具。
  • 我应该使用哪个 Experience Builder 模板?
    根据您使用的 Experience Builder 模板,您可以使用两种编程模型构建 Experience Builder 站点:Lightning Web 组件模型和原始 Aura 组件模型。Build Your Own (LWR) 模板基于新的 Lightning Web 运行时 (LWR),只能与 Lightning Web 组件一起使用,而不能与 Aura 组件一起使用。其他模板基于 Aura 组件模型,可以同时使用 Lightning Web 组件和 Aura 组件。
  • Experience Cloud 开发人员发行说明 使用 Salesforce 发行说明
    了解 Experience Cloud 开发人员体验的最新更新和更改。

准备工作

在开始开发自定义 Experience Builder 站点之前,请确保您 熟悉在 Lightning 中开发。

您可以在 EnterprisePerformanceUnlimited 和 Developer Edition 或沙盒中创建 Experience Builder 站点和 Lightning 组件。

要成功使用本指南,需要:

  • 启用了数字体验的组织
  • 基于 Experience Builder 模板或 Lightning 的新站点或现有站点 螺栓解决方案
  • 熟悉使用 Experience Builder
  • 具有开发 Lightning 组件和使用 CSS 的经验

Lightning 开发资源

不熟悉 Lightning 开发?然后查看这些资源。

Lightning Aura 组件 开发者指南

所有 Aura 的首选指南。基本概念和方法 指南文档构成了本指南的基石。想想 Experience Cloud 开发人员指南作为开发系列的第 2 部分;它对你没有用,直到 您熟悉了第 1 部分。

Lightning Web 组件 开发者指南

了解如何开发 Lightning Web 组件,即使用 HTML 构建的自定义 HTML 元素 和现代 JavaScript。

LWR 体验站点 云开发人员指南

使用“构建自己的网站”(LWR) 开发加载速度快且可扩展的站点 Experience Cloud 的模板。此模板基于最新的 Lightning Web 运行时 (LWR) 和 Lightning Web 组件 (LWC) 编程模型。

Aura 组件基础知识 (Trailhead Module)

使用 Aura 组件构建具有可重用 UI 组件的新式 Web 应用程序。学习核心 Lightning 组件概念并构建可运行的简单费用跟踪器应用程序 在独立应用程序、Salesforce 移动应用程序或 Lightning Experience 中。

构建 Lightning Web 组件 (Trailhead Trail)

使用 JavaScript 和 HTML 开发可重用的 Lightning Web 组件。

快速入门:Aura 组件 (Trailhead Project)

创建第一个组件,用于呈现组织中的联系人列表。

构建自定义主题布局 Experience Builder Sites 的组件(Trailhead 项目)

使用主题布局组件自定义 Experience Builder 站点。

闪电组件 性能最佳实践(博客文章)

了解影响组件性能的 Lightning 特性,并获得 优化组件的最佳实践。

Experience Cloud 资源

不熟悉 Experience Cloud?然后查看这些资源。

设置和管理体验 Cloud Sites(帮助)

使用模板创建品牌网站,直接与您的客户互动,以及 合作伙伴在线。

通过经验扩大您的影响力 云 (Trailhead Trail)

了解开始使用 Salesforce Experience Cloud 所需的工具。

体验云 概述(帮助)

及时了解其他 Experience Cloud 资源。

什么是 Salesforce Lightning?

借助 Salesforce Lightning,您可以更轻松地为任何设备构建响应式应用程序, 并包含 Lightning 组件框架和为开发人员提供的有用工具。闪电网络包括这些技术。

  • Lightning 组件可加速开发和应用性能。开发定制 其他开发人员和管理员可用作可重用构建基块的组件 自定义 Experience Builder 站点、Salesforce 移动应用程序和 Lightning 经验。
  • Lightning 应用程序生成器使管理员能够直观地构建 Lightning 页面,无需代码, 使用现成的和定制的 Lightning 组件。制作您的 Lightning 组件 在 Lightning 应用程序生成器中可用,因此管理员可以构建自定义用户界面 没有代码。
  • Experience Builder 使管理员能够使用模板直观地构建站点,并且 组件。使您的 Lightning 组件在 Experience Builder 中可用,以便 管理员无需代码即可构建网站页面。

一些使用 Lightning 框架构建的 Salesforce 产品包括:

  • Experience Builder 模板
  • 闪电 解决 方案
  • 闪电体验
  • Salesforce 移动应用程序

注意

您无需启用 Lightning Experience 即可使用 Experience Builder 模板 或开发 Lightning 组件。Experience Builder 站点使用相同的底层技术 作为 Lightning Experience,但它们彼此独立。

我应该使用哪个 Experience Builder 模板?

根据您使用的 Experience Builder 模板,您可以构建 Experience 使用两种编程模型构建站点:Lightning Web 组件模型和原始模型 Aura 组件模型。Build Your Own (LWR) 模板基于新的 Lightning Web 运行时 (LWR),只能与 Lightning Web 组件一起使用,而不能与 Aura 组件一起使用。其他 模板基于 Aura 组件模型,可以使用 Lightning Web 组件和 光环组件。

建立你自己的

提供每个Experience Builder站点所需的基本页面:主页、创建记录、 错误、记录明细、记录列表、相关记录列表、搜索、检查密码、忘记 密码、登录名、登录错误和注册。根据需要添加更多页面和组件 您正在构建的体验。要优化网站的外观,请自定义您的品牌 和主题。

构建自己的 (LWR)

由新的 Lightning Web 运行时 (LWR) 平台提供支持,这个可自定义的模板 提供无与伦比的页面性能,提高开发人员的工作效率。快速构建 像素完美的页面,并开发 Lightning Web 组件和主题,以匹配您独特的 品牌。

适合熟悉开发的开发人员、咨询合作伙伴和 ISV 自定义 Lightning Web 组件,并使用 Salesforce DX、用户界面 API 和 顶点。

查看 LWR 站点获取体验 云指南。

客户账户门户

一个私密且安全的地方,供客户访问和更新其帐户信息。 通过让客户在 门户。客户可以查看和支付发票、更新其帐户信息以及搜索 您的知识库,用于回答他们最常见问题。

顾客服务

功能强大、响应迅速的自助服务模板,具有多个预构建的主题选项。这 Customer Service 模板允许用户将问题发布到社区、搜索和查看 文章、协作,并通过创建案例联系支持代理。支持知识, Chatter 问题和案例。

合作伙伴中心

专为渠道销售工作流程设计的灵活、响应迅速的模板。招募、建设、 并发展您的合作伙伴网络,以品牌化的方式共同推动渠道销售和营销 在线空间。轻松配置销售线索分销、交易注册和营销 活动。在中央空间中共享培训材料和销售材料,并使用 用于跟踪管道的报表。

帮助中心

一个公开您创建的文章的公共访问自助服务社区 可从知识库获取。您可以减轻客户支持团队的负担,并且 您的用户会因为找到自己的解决方案而感到满意。

Experience Cloud 开发人员发行说明

使用 Salesforce 发行说明了解 Experience Cloud 开发人员体验。

有关新功能和更改的功能,请参阅 Salesforce 发行说明的 Experience Cloud 部分。您还可以查找 Experience Cloud 在“新建和更改的项目”中 Salesforce 发行说明中的开发人员。

开发 Experience Builder 站点:基础知识

了解开发者控制台开发工具,以及如何创建基本的拖放操作 光环组件,以及在此过程中要考虑的提示。

  • 使用开发者控制台 开发者控制台
    提供了用于开发 Aura 组件和应用程序的工具。
  • 为 Experience Builder 配置拖放式 Aura 组件 在Experience Builder
    中使用自定义Aura组件之前,需要执行一些配置步骤。
  • 在Experience Builder
    中公开组件属性 您可以使用设计资源来控制在Experience Builder中公开哪些属性。设计资源与组件位于同一文件夹中。它描述了 Aura 组件的设计时行为,即可视化工具在页面或应用中显示组件所需的信息。
  • 为 Experience Builder
    配置 Aura 组件的提示和注意事项 在为 Aura 站点创建 Aura 组件和组件捆绑包时,请牢记这些准则。
  • 支持的 Aura 组件、接口和事件 基于 Aura 的 Experience Builder 站点并非支持所有 Aura 组件、接口和事件
    。有些仅适用于 Salesforce 移动应用程序或 Lightning Experience。在自定义您的网站之前,请查看可用的内容。
  • 个性化目标开发人员和组名称
    在使用 Connect REST API 或元数据 API 个性化 Experience Builder 站点时,确定体验变体目标的开发人员名称和组名称。
  • 遵守用户的个人信息可见性设置 具有门户和站点的组织提供特定设置
    ,以向其他用户隐藏用户的个人身份信息和联系信息。这些设置不会在 Apex 中强制执行,即使使用 Apex 安全功能(如子句或方法)也是如此。要对来宾或外部经过身份验证的用户隐藏特定字段,请遵循下面概述的示例代码。WITH SECURITY_ENFORCEDstripInaccessible

使用开发者控制台

开发者控制台提供了用于开发 Aura 组件和 应用。

开发人员控制台使您能够执行这些功能。

  • 使用菜单栏 (1) 创建或打开这些 Lightning 资源。
    • 应用
    • 元件
    • 接口
    • 事件
    • 令 牌
  • 使用工作区 (2) 处理 Lightning 资源。
  • 使用侧边栏 (3) 创建或打开客户端资源,这些资源是 特定组件捆绑包。
    • 控制器
    • 助手
    • 风格
    • 文档
    • 渲染
    • 设计
    • SVG

为 Experience Builder 配置拖放式 Aura 组件

在Experience Builder中使用自定义Aura组件之前,有几个 要执行的配置步骤。

1. 将界面添加到你的 元件

显示为 拖放组件 在Experience Builder中,组件必须实现接口。forceCommunity:availableForAllPageTypes

创建 Aura 组件后,该组件将显示在 Components 中 组织中所有 Aura 站点的面板。

下面是一个简单的“Hello World”组件的示例代码。组件必须 命名为 componentName.cmp

注意

要使 资源,例如组件,可在您自己的组织外部使用,请用 标记它。例如,如果您希望组件在已安装的软件包中可用,请使用 由 Experience Builder 用户提供 在另一个 组织。access=”global”access=”global”

<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
    <aura:attribute name="greeting" type="String" default="Hello" access="global" />
    <aura:attribute name="subject" type="String" default="World" access="global" />

    <div>{!v.greeting}, {!v.subject}!</div>
</aura:component>

警告

当您将自定义组件添加到 site,它们可以绕过您为来宾用户设置的对象级和字段级安全性 (FLS) 轮廓。Lightning 组件在引用对象或检索对象时不会自动强制执行 CRUD 和 FLS 从 Apex 控制器。这意味着框架继续显示记录和 用户没有 CRUD 权限和 FLS 可见性的字段。您必须手动操作 在 Apex 控制器中强制执行 CRUD 和 FLS。

2. 将设计资源添加到组件包中

设计资源控制公开的组件属性 在 Experience Builder 中。这 设计资源与 .cmp 资源位于同一文件夹中,并且 描述 Aura 组件的设计时行为 – 可视化工具所需的信息 以在页面或应用程序中显示组件。

例如,设置属性的默认值,或创建 Aura 组件属性 可供管理员在 Experience Builder 中编辑,您的 组件包需要设计资源。下面是与“Hello World”组件捆绑在一起的设计资源。一个 设计资源必须命名为 componentName.design

<design:component label="Hello World">
    <design:attribute name="greeting" label="Greeting" />
    <design:attribute name="subject" label="Subject" description="Name of the person you want to greet" />
</design:component>

自选。将 SVG 资源添加到组件包

要为组件定义自定义图标,请将 SVG 资源添加到组件包中。 该图标显示在 Experience Builder 组件中的组件旁边 面板。

如果不包含 SVG 资源,系统将使用默认图标 (默认组件图标)。

下面是一个简单的红色圆圈 SVG 资源,用于“Hello World”组件。An SVG 资源必须命名为 componentName.svg

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 
<svg xmlns="http://www.w3.org/2000/svg"
     width="400" height="400">
  <circle cx="100" cy="100" r="50" stroke="black"
    stroke-width="5" fill="red" />
</svg>

自选。将 CSS 资源添加到组件包

要设计你的 自定义组件,将 CSS 资源添加到组件包中。

这是 CSS 的 简单的类,以配合“Hello World”组件。CSS 资源必须命名为 componentName.css

.THIS .greeting {
    color: #ffe4e1;
    font-size: 20px;
}

创建类后,将其应用于组件。

<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
    <aura:attribute name="greeting" type="String" default="Hello" access="global" />
    <aura:attribute name="subject" type="String" default="World" access="global" />

    <div class="greeting">{!v.greeting}, {!v.subject}!</div>
</aura:component>

在Experience Builder中公开组件属性

您可以使用设计资源来控制在体验中显示哪些属性 建筑工人。设计资源与组件位于同一文件夹中。它描述了 Aura 组件的设计时行为 – 可视化工具显示 组件。

要使 Aura 组件属性可供管理员在 Experience Builder 中编辑,请在设计中为该属性添加一个节点 资源。当您将属性标记为必需时,该属性会自动显示在Experience Builder中,除非它 为其分配了默认值。design:attribute

您必须使用 default 指定必需的属性 在设计的组件定义中未标记为必需的值和属性 资源,使它们对用户显示。设计资源仅支持 、 或 类型的属性。intstringboolean

对于拖放组件,公开 属性将显示在组件的属性面板中。

对于主题布局组件,当主题布局 在“设置”|”主题面积。

为 Experience Builder 配置 Aura 组件的提示和注意事项

在为 光环网站。

组件

  • 使用设计文件元素中的属性为组件指定一个友好名称,例如 .label<design:component label=”foo”>
  • 将组件设计为填充 100% 的区域宽度(包括边距) 它们显示在。
  • 确保组件在声明性中提供适当的占位符行为 工具(如果需要交互)。
  • 切勿让组件显示空白框。想想其他网站是如何工作的。例如 Facebook 在源项从服务器返回之前显示源的轮廓, 这提高了用户对 UI 响应能力的感知。
  • 如果组件依赖于触发的事件,请为其指定之前显示的默认状态 事件触发。
  • 使用标准设计标记设置组件样式,使其与 Salesforce设计系统。
  • 请记住,Lightning Locker 是针对创建的所有 Aura 组件强制执行的 在 Summer ’17(API 版本 40.0)及更高版本中,当组织中启用了 Lightning Locker 时,并且 网站。在组织级别,如果 Lightning Web Security 尚未使用 Lightning Locker,则 Lightning Locker 正在使用 已启用。请参阅开发安全站点:CSP、LWS 和 Lightning Locker。
  • 对于自定义组件,当您在体验中使新属性可供编辑时 构建器,在进行网站翻译时,请牢记以下注意事项: 如果组件正在使用中 在Experience Builder的页面上,从页面中删除组件并将其替换为 更新后的版本。否则,当您导出网站内容进行翻译时, 对于导出文件中的该组件实例,将省略您添加的属性。如果 该组件包含已翻译的内容,请先将网站内容导出到 保留现有翻译。然后将组件替换为更新的 版本。

属性

  • 使用设计文件来控制向Experience Builder公开哪些属性。
  • 使您的属性易于使用,便于管理员理解。不要暴露 SOQL 查询、JSON 对象或 Apex 类名。
  • 为必需属性提供默认值,以避免用户体验不佳。当 具有必需属性且没有默认值的组件将添加到体验中 生成器,它看起来无效。
  • 使用基本支持的类型 (, , ) 公开的属性。stringintegerboolean
  • 为元素中的整数属性指定最小值和最大值,以控制接受值的范围。<design:attribute>
  • 请注意,字符串属性可以为数据源提供一组预定义的 值,允许属性将其配置公开为选择列表。
  • 为属性提供具有友好显示名称的标签。
  • 包括描述以解释预期数据并提供指南,例如 数据格式或预期的值范围。描述文本在 属性面板。
  • 若要删除实现接口的组件的设计属性,请首先 在删除 design 属性之前,从组件中删除接口。然后 重新实现接口。如果在网站页面中引用了该组件,则必须删除 该组件,然后才能更改它。forceCommunity:availableForAllPageTypes

支持的 Aura 组件、接口和事件

并非所有 Aura 组件、接口和事件都支持基于 Aura 的体验 建设者网站。有些仅适用于 Salesforce 移动应用程序或 Lightning Experience。 在自定义您的网站之前,请查看可用的内容。

Aura 组件、接口和事件记录在组件库中。每 组件、接口和事件指示它支持哪种体验。

个性化目标开发人员和组名称

在以下情况下确定体验变体目标的开发人员名称和组名称 使用 Connect REST API 或元数据 API 对 Experience Builder 站点进行个性化设置。

对于 Connect Rest API 的 Target Input 请求正文或 Audience 元数据类型的 PersonalizationTargetInfo 子类型,您必须指定:

  • 属性中的目标组名称groupName
  • 属性中的目标开发人员名称targetValue

若要确定这些名称,必须从 站点的 ExperienceBundle 文件夹。

确定这些值的方式会有所不同,具体取决于您是否定位到网页 变体、品牌集、组件 可见性或组件属性。

页面变体

要确定页面变体的组名称和开发人员名称,请打开相关的 路由文件和相应的视图文件。例如,打开 routes 文件夹中的 Home.json 文件和 views 文件夹中的 Home.json 文件。组名称Format: ,其中 是路由 JSON 文件的属性。route.idroute.idid

例: 63d9b8fe-99fc-4f54-b784-5034e09a6670开发商名称格式: ,其中:route.label_view.label_Page

  • route.label是路由 JSON 文件的属性。label
  • view.label是视图 JSON 文件的属性。label

例: Home_Gold_Home_Page

品牌集

若要确定品牌集的组名称和开发人员名称,请打开相关的 品牌设置文件和相应的主题文件。例如,在客户服务网站中, 打开 themes 文件夹中的 customerService.json 文件和 brandingSets 文件夹中的 customerService.json 文件。组名称格式: ,其中 是 主题 JSON 文件。theme.id$#$Brandingtheme.idid

例: 70ebee67-0fca-421e-ac32-12879ee55936$#$Branding开发商名称格式: ,其中:theme.developerName_brandingSet.label_Branding

  • theme.developerName是主题 JSON 文件的属性。developerName
  • brandingSet.label是品牌集 JSON 文件的属性。label

例: service_Customer_Service_Branding

组件可见性

确定组名和 开发人员名称 对于组件可见性,请打开包含该组件的视图文件。为 例如,打开 views 文件夹中的 Home.json 文件。组名称格式: ,其中:view.id$#$component.id

  • view.id是属性 的视图 JSON 文件。id
  • component.id是视图 JSON 文件中组件的属性。id

例: f8c9b721-0a1d-45bb-954f-3277a0501892$#$823cb1c0-697f-4b33-8fa4-a925aef98cf7开发商名称格式: ,其中:view.label_componentName_Component

  • view.label是视图 JSON 文件的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Home_Headline_Component

注意

如果 必要时,您可以向开发人员名称添加一个数值以使其唯一。为 例。Home_Page_Rich_Content_Editor_Component1

组件属性

对于组件属性,组和开发人员名称会有所不同,具体取决于 组件位于视图正文中,或者位于主题布局的页眉或页脚中。

视图主体中的组件

若要确定视图正文中组件的组和开发人员名称,请打开视图 包含组件的文件。例如,打开 Home.json 文件 在“视图”文件夹中。组名称格式: ,其中:view.id$#$component.id

  • view.id是属性 的视图 JSON 文件。id
  • component.id是视图 JSON 文件中组件的属性。id

例: f8c9b721-0a1d-45bb-954f-3277a0501892$#$823cb1c0-697f-4b33-8fa4-a925aef98cf7开发商名称格式: ,其中:view.label_componentName_Component_Properties

  • view.label是视图 JSON 文件的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Home_Headline_Component_Properties

注意

如有必要,您可以向开发人员名称添加一个数值,使其唯一。为 例。Home_Page_Rich_Content_Editor_Component1

页眉或页脚中的组件

确定 主题布局,打开包含组件的主题文件。例如,在 Customer 中 服务站点,在主题中打开 customerService.json 文件 文件夹。组名称格式: ,其中:themeLayout.id$#$component.id

  • themeLayout.id是包含组件的布局的属性。id
  • component.id是布局中组件的属性。id

例: 06ce2db9-2c79-4ccc-9ca8-94c7b50efb6b$#$c55d1908-fe6b-47e8-b41e-70ad05aeb490组件属性组名称开发商名称格式: ,其中:themeLayout.label_componentName_Component_Properties

  • themeLayout.label是包含组件的布局的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Default_Navigation_Menu_Component_Properties组件属性开发人员名称

遵守用户的个人信息可见性设置

具有门户和站点的组织提供特定设置来隐藏用户的个人信息 来自其他用户的身份信息和联系信息。这些设置不会在 Apex 中强制执行, 即使具有 Apex 安全功能,例如子句或方法。对来宾或外部隐藏特定字段 经过身份验证的用户,请遵循下面概述的示例代码。

WITH SECURITY_ENFORCEDstripInaccessible

若要在 User 对象中隐藏用户的个人信息,请执行以下操作:

public User[] fetchUserDetail(Set userIds) { 
    // Query all the fields of user which we are expected in user record to show that on UI or to 
    // perform some business logic. 
    User[] userRecords = [SELECT id, username, communitynickname, firstname, lastname, title 
    FROM User WHERE id IN :userIds]; 
 
    for (User userRecord : userRecords) { 
        // User is not fetching his own record and is not standard user. 
        if(userRecord.id != UserInfo.getUserId() && !Auth.CommunitiesUtil.isInternalUser()) { 
            // clear-out all PII fields form user record which we have queried above. 
            userRecord.username = ''; 
            userRecord.title = ''; 
        } 
    } 
    return userRecords;
}

遵守用户在社区中的联系信息可见性设置,或者 门户,我们检查与特定字段关联的首选项并显示或隐藏数据 因此。对于用户在 Experience Cloud 中的联系人可见性设置 网站:

public User[] fetchUserRecordRespectingFLVPreferences(Set<Id> userIds) {

    //Fetch users records along with fields specific user preferences.
    User[] userRecords = [SELECT email, UserPreferencesShowEmailToExternalUsers, UserPreferencesShowEmailToGuestUsers FROM User WHERE id IN :userIds];

    // If context user is internal user then return result without any restriction.
    if (Auth.CommunitiesUtil.isInternalUser()) {
        return userRecords;
    }

    // If user is guest user then return result as per the user's UserPreference for the fields related to the Guest user visibility.
    if (Auth.CommunitiesUtil.isGuestUser()){
        return fetchUserRecordForGuestUser(userRecords);
    }

    // Return result as per the user's UserPreference for the fields related to the External user visibility 
    return fetchUserRecordForExternalUser(userRecords);

}

// Apply Field level visibilty logic by checking user's UserPreferences for the fields related to the External user visibility.
public User[] fetchUserRecordForExternalUser(User[] userRecords) {

    for(User userRecord : userRecords) {

        //Clear field of user record when context user fetching other user's record and Field Level Visibility for that field is set to Restricted.
        if(userRecord.id != UserInfo.getUserId() && !userRecord.UserPreferencesShowEmailToExternalUsers)
        {
            userRecord.email = '';
        }

    }   

    return userRecords;         
}

// Apply Field level visibilty logic by checking user's UserPreferences for the fields related to the Guest user visibility.
public User[] fetchUserRecordForGuestUser(User[] userRecords) {

    for(User userRecord : userRecords) {

        //Clear field of user record when context user fetching other user's record and user preference for that field is NOT set to public.
        if(!userRecord.UserPreferencesShowEmailToGuestUsers)
        {
            userRecord.email = '';
        }

    }   

    return userRecords;       

}

部署和检索元数据

使用 deploy() 和 retrieve() 调用移动元数据(XML 文件) 在 Salesforce 组织和本地文件系统之间。检索 XML 文件后 在文件系统中,您可以在源代码控制系统中管理更改,复制和粘贴 代码或设置配置,对组件进行差异更改,并执行许多其他基于文件的操作 开发操作。您可以随时将这些更改部署到另一个 Salesforce 组织。

注意

Ant 迁移工具使用 deploy() 和 retrieve() 调用来移动元数据。 如果您使用这些工具,则与元数据 API 的交互是无缝且不可见的。因此 大多数开发人员发现使用这些工具比编写直接调用 deploy() 和 retrieve() 的代码要容易得多。

XML 文件中的数据使用英语(美国)区域设置进行格式设置。此格式 确保对依赖于区域设置的字段(如日期字段)的解释一致 在使用不同语言的组织之间进行数据迁移期间。组织可以 支持多种语言向用户展示。

deploy() 和 retrieve() 调用主要用于 以下开发方案:

  • 在沙盒组织中开发自定义应用程序(或自定义)。后 完成开发和测试,然后部署应用程序或自定义项 使用元数据 API 进入生产组织。
  • 在 Developer Edition 组织中对应用程序进行团队开发。开发后 并完成测试,然后您可以通过 Lightning Platform 分发应用程序 AppExchange。

每次检索到最大数量的 90% 或更多时,您都会收到 API 通知 您可以使用元数据 API 一次性部署的自定义字段。自定义的最大数量 一个部署的字段为 45,000。在一个包.xml文件中检索到的自定义字段包括: 1) package.xml 的 CustomObjects 部分中每个对象的字段总和和 2) package.xml 的 CustomFields 部分中自定义字段的总和。

您仍然可以检索超过可部署最大值,直至达到检索文件总大小的限制。但是你 必须使用多个部署来部署所有自定义字段。

警告:您已检索到 47,000 个 CustomField 实例。无法重新部署所有这些 实例;最大值为 45,000。

使用 Zip 文件部署和检索元数据

和调用用于部署和检索 .zip 文件。在 .zip 文件是一个项目清单 (package.xml),其中列出了要执行的操作 检索或部署,以及组织到文件夹中的一个或多个 XML 组件。

deploy()retrieve()

注意

组件是元数据类型的实例。例如,是自定义对象的元数据类型,并且 该组件是 自定义对象。CustomObjectMyCustomObject__c

在 .zip 文件中检索或部署的文件可能是未打包的组件 驻留在组织中(例如标准对象)或打包组件 驻留在命名包中。

注意

您可以部署或 一次最多可检索 10,000 个文件。AppExchange 软件包使用不同的限制: 最多可包含 35,000 个文件。已部署或检索的 .zip 的最大大小 文件大小为 39 MB。如果文件在解压缩的文件夹中解压缩,则大小限制 是 400 MB。

  • 如果使用 Ant 迁移工具执行 部署解压后的文件夹,首先压缩文件夹中的所有文件。这 解压缩文件夹中未压缩组件的最大大小为 400 MB 或更少 取决于压缩比。如果文件具有高压缩比, 您总共可以迁移大约 400 MB,因为压缩的大小 将小于 39 MB。但是,如果组件不能被压缩太多,比如 二进制静态资源,可以迁移小于 400 MB。
  • 元数据 API base-64 对组件进行编码 它们被压缩了。生成的 .zip 文件不能超过 50 MB,即 SOAP 消息的限制。Base-64 编码会增加有效负载的大小,因此 在编码之前,压缩的有效负载不能超过大约 39 MB。
  • 您可以执行大 对象仅在定义其索引时才被定义。如果在安装程序中创建了一个大对象,并且 尚未定义索引,则无法检索它。retrieve()

每个 .zip 文件都包含一个项目清单、一个名为 package.xml 的文件以及一组包含 组件。清单文件定义您尝试执行的组件 在 .zip 文件中检索或部署。清单还定义了 API 版本 用于部署或检索。

注意

您可以编辑项目 清单,但如果您修改它所包含的组件列表,请小心。当你 部署或检索组件时,元数据 API 会引用 清单,而不是 .zip 文件中的目录。

下面是一个示例包 .xml 文件。您可以检索 通过在元素中指定元数据类型的 fullName 字段值来获取元数据类型的单个组件。您还可以 使用 检索元数据类型的所有组件。members<members>*</members>

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MyCustomObject__c</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>Standard</members>
        <name>Profile</name>
    </types>
    <version>59.0</version>
</Package>

可以在 package.xml 中定义以下元素。

  • <fullName>包含服务器端的名称 包。如果不存在,则 package.xml 定义客户端包。<fullName>unpackaged
  • <types>包含元数据类型的名称 (例如,) 和 成员(例如,) 为 检索或部署。您可以在清单文件中添加多个元素。CustomObjectmyCustomObject__c<types>
  • <members>包含组件的 fullName,例如 。listMetadata() 调用可用于 确定特定组件的 fullName 元数据类型(如果要检索单个组件)。对于许多元数据 类型,您可以将 中的值替换为通配符(星号) 而不是单独列出每个成员。有关特定 type 以确定该类型是否支持通配符。 每个组件 在元数据 API 部署中必须具有唯一的名称。解析为 重复项,例如一个符号和 UTF-8 编码符号以及一对名为 xyz.typename 和 xyz.typename-meta.xml 仍然是 重复。MyCustomObject__cmembers*注意在元素中指定 Security,在名称中指定 Settings 元素。<members>
  • <name>包含元数据类型,例如 或 。在 目录。任何扩展元数据的元数据类型都是有效值。输入的名称 必须与元数据 API WSDL 中定义的元数据类型匹配。有关列表,请参阅元数据类型。CustomObjectProfile
  • <version>是使用的 API 版本号 部署或检索 .zip 文件时。当前有效值为 。59.0

有关演示如何工作的更多示例包 .xml 清单文件 使用不同的元数据子集,请参阅示例包 .xml 清单 文件。

要删除组件,请参阅从 组织。

部署缓慢

如果在服务器停机期间进行基于文件的元数据 API 部署,例如 Salesforce 服务升级时,部署所需的时间可能比预期的要长。发生此行为 因为组件部署和验证都是从头开始重试的,所以在 服务已恢复。但是,如果 Apex 测试是部署的一部分,则只有不是部署的测试 在停机时间运行之前运行。

此行为会影响基于文件的部署和检索、更改集、某些包安装 和升级、第二代托管软件包创建以及部署和检索已开始 从 Salesforce CLI 或 Salesforce VS Code 扩展。它不影响基于 CRUD 元数据操作。

如果您的实例需要进行计划的服务升级,请避免在 服务升级。要检查您的 Salesforce 实例是否需要升级,请检查 Salesforce 信任。Salesforce 每年执行 3 次重大服务升级和其他 全年维护更新。

检索作业的状态是否为“挂起”?

如果为单个启动多个并发检索操作 org,元数据 API 会自动将其中一些作业放入队列中,如果有必要的话 服务保护。如果检索作业的状态为 ,则为 在队列中。当其中一个活动检索作业完成时,元数据 API 将接受挂起的作业 从队列中激活它。如果检索作业的状态为 ,则该作业处于活动状态。该过程将重复进行,直到作业队列 清除。PendingInProgress

有关更多信息,请参阅 Salesforce 开发人员限制和分配快速中的元数据限制 参考资料。

示例包 .xml 清单文件

本部分包括示例包 .xml 清单文件,这些文件演示如何工作 具有不同的元数据子集。清单文件可以包含多个<类型>元素 因此,如果需要,可以将各个示例合并到一个 Package.xml 清单文件中 在一个批处理中处理所有元数据。

列出了以下示例:

  • 标准 对象
  • 全部定制 对象
  • 标准选择列表 领域
  • 定制和标准 领域
  • 标准列表视图 对象
  • 安全 设置
  • 分配规则,自动响应 规则、升级规则
  • 共享规则
  • 托管组件 访问

有关清单文件结构的更多信息,请参阅使用 Zip 文件部署和检索元数据。

标准对象

此示例包 .xml 清单文件说明了如何工作 替换为标准 Account 对象。检索或部署标准对象包括 所有自定义字段和标准字段,但不可自定义的标准字段除外。 支持所有自定义字段。只有您可以自定义的标准字段是 支持,即可以添加帮助文本或启用的标准字段 历史记录跟踪或 Chatter 摘要跟踪。其他标准字段不是 支持,包括系统字段(如 CreatedById 或 LastModifiedDate)和自动编号字段。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

请注意如何使用标准 Account 对象,方法是将其指定为 CustomObject 类型。但是,您不能使用星号通配符来处理所有 标准对象;每个标准对象必须按名称指定。

所有自定义对象

此示例包 .xml 清单文件说明了如何工作 替换为所有自定义对象。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

此清单文件可用于检索或部署所有自定义对象,但不是全部 标准对象。

标准选择列表字段

在 API 版本 38.0 及更高版本中,StandardValueSet 类型表示标准 选择列表。选择列表不再像早期版本那样由字段表示。 此示例包 .xml 将行业标准选择列表表示为 StandardValueSet 类型。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Industry</members>
        <name>StandardValueSet</name>
    </types>
    <version>59.0</version>
</Package>

注意

标准值集的名称区分大小写。

行业标准值集对应于 API 版本 37.0 及更早版本中的 Account.Industry 或 Lead.Industry 字段。此示例显示 Account.Industry 选择列表的 package.xml 示例。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Account.Industry</members>
        <name>CustomField</name>
    </types>
    <version>37.0</version>
</Package>

注意

选择列表字段的名称区分大小写。

请注意字段中的语法,其中是对象的名称,例如 和 标准选择列表字段的名称,例如“行业”。objectName.picklistField<members>objectNameAccountpicklistField

下一个 package.xml 示例表示商机团队角色 在 API 版本 38.0 及更高版本中。将商机团队角色指定为 SalesTeamRole 标准值集。商机团队角色 具有与“客户团队”角色相同的选择列表值。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>SalesTeamRole</members>
        <name>StandardValueSet</name>
    </types>
    <version>59.0</version>
</Package>

SalesTeamRole 标准值集对应于以下值之一 API 版本 37.0 及更早版本中的字段名称:OpportunityTeamMember.TeamMemberRole、UserAccountTeamMember.TeamMemberRole、UserTeamMember.TeamMemberRole 和 AccountTeamMember.TeamMemberRole。 商机团队角色 在此示例包 .xml 中表示为 OpportunityTeamMember.TeamMemberRole 字段。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>OpportunityTeamMember.TeamMemberRole</members>
        <name>CustomField</name>
    </types>
    <version>37.0</version>
</Package>

了解标准值集的名称以及它们如何映射到选择列表字段 名称,请参阅 StandardValueSet 名称和标准选择列表字段。

自定义字段和标准字段

此示例包 .xml 清单文件说明了如何工作 在自定义和标准对象中使用自定义字段,在标准中使用标准字段 对象。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MyCustomObject__c.MyCustomField__c</members>
        <name>CustomField</name>
    </types>
    <types>
        <members>Account.SLA__c</members>
        <members>Account.Phone</members>
        <name>CustomField</name>
    </types>
    <version>59.0</version>
</Package>

请注意 字段 where 是对象的名称(如 Account),是自定义或标准字段的名称,例如表示服务级别协议的 SLA 选择列表字段 选择。MyCustomObject 中的 MyCustomField 自定义域 自定义对象由其全名 唯一标识。同样,“客户标准”对象中的“电话标准”字段为 由其全名 .objectName.field<members>objectNamefieldMyCustomObject__c.MyCustomField__cAccount.Phone

支持所有自定义字段。只有您可以自定义的标准字段是 支持,即可以添加帮助文本或启用的标准字段 历史记录跟踪或 Chatter 摘要跟踪。其他标准字段不是 支持,包括系统字段(如 CreatedById 或 LastModifiedDate)和自动编号字段。

标准对象的列表视图

检索标准对象的列表视图的最简单方法是检索 对象。列表视图包含在检索到的组件中。请参阅部分 有关标准对象的本主题。

如果您不想检索所有 对象的详细信息。此示例包 .xml 清单文件 阐释如何使用标准 Account 对象的列表视图。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Account.AccountTeam</members>
        <name>ListView</name>
    </types>
    <version>59.0</version>
</Package>

请注意字段中的语法,其中是对象的名称,例如 Account,并且是 View Unique 列表视图的名称。如果检索此列表视图,则组件 存储在 objects/Account.object 中。objectName.listViewUniqueName<members>objectNamelistViewUniqueName

要检索包,请在调用 时在 RetrieveRequest 的 packageNames 字段中设置包的名称。包 .xml 清单文件 会自动填充到检索到的文件中。元素 在 package.xml 中包含检索到的包的名称。retrieve().zip<fullName>

如果在元素中使用星号通配符来检索特定元数据类型的所有组件,则检索到的 内容不包括托管包中的组件。<members>

有关托管包的详细信息,请参阅第二代托管包 打包开发人员指南。

检索托管包中的组件的最简单方法是检索 如前所述,通过在 的 packageNames 字段中设置包的名称来完成包。以下示例包.xml 清单文件演示了 检索包中的单个组件。RetrieveRequest

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>myns__MyCustomObject__c</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

请注意字段中的 __ 语法,其中是包的命名空间前缀,是对象的名称。namespacePrefixobjectName<members>namespacePrefixobjectName命名空间前缀是 1 个字符到 15 个字符的字母数字标识符 将您的包及其内容与其他发布商的包区分开来 包。有关详细信息,请参阅创建和 为第二代托管注册命名空间 包。

安全设置

此示例包 .xml 清单文件说明了如何工作 使用组织的安全设置。在元素中指定 Security,在名称中指定 Settings 元素。<members>

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Security</members>
        <name>Settings</name>
    </types>
    <version>59.0</version>
</Package>

分配规则、自动响应规则、升级 规则

分配规则、自动响应规则和升级规则使用 用于访问规则集的不同包 .xml 类型名称或 对象类型的单个规则。例如,以下示例 package.xml 清单文件演示了如何访问 仅案例和潜在顾客的组织分配规则。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Case</members>
        <members>Lead</members>
        <name>AssignmentRules</name>
    </types>
    <version>59.0</version>
</Package>

以下示例包.xml 清单 文件说明了如何仅访问“samplerule” 案例分配规则 以及“newrule”潜在客户分配规则。请注意,类型名称是 and not 。

AssignmentRuleAssignmentRules

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Case.samplerule</members>
        <members>Lead.newrule</members>
        <name>AssignmentRule</name>
    </types>
    <version>59.0</version>
</Package>

同样,用于访问单个自动响应规则和 升级规则,使用 and 代替 和 。

AutoResponseRuleEscalationRuleAutoResponseRulesEscalationRules

共享规则

在 API 版本 33.0 及更高版本中,可以检索和部署所有共享规则 标准对象和自定义对象。此示例包 .xml 清单 文件说明了如何使用组织的共享规则,例如 检索潜在顾客对象的基于条件的特定共享规则,检索 所有对象的所有基于所有权的共享规则,并检索所有对象 Account 对象的基于区域的共享规则。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Lead.testShareRule</members> 
         <name>SharingCriteriaRule</name>
    </types>
    <types>
        <members>*</members> 
        <name>SharingOwnerRule</name>
    </types>
    <types>
        <members>Account.*</members>
        <name>SharingTerritoryRule</name>
    </types>
    <version>33.0</version>
</Package>

托管组件访问

在 API 版本 29.0 及更高版本中,您可以检索和 在配置文件中部署以下托管组件的访问设置,以及 权限集:

  • 顶点类
  • 应用程序
  • 自定义字段权限
  • 自定义对象权限
  • 自定义选项卡设置
  • 外部数据源
  • 记录类型
  • Visualforce 页面

在 API 版本 51.0 及更高版本中,您可以检索和部署登录的访问设置 流。

检索和部署托管组件权限时,请指定命名空间 后跟两个下划线。不支持通配符。

例如,假设您安装了一个命名空间为 MyNamespace 且自定义对象为 JobRequest__c 的托管包。将包中JobRequest__c的对象权限设置为自定义配置文件 MyProfile,您需要将以下内容添加到 .profile 文件中。

要部署,请执行以下操作:

<objectPermissions>
    <allowCreate>true</allowCreate>
    <allowDelete>true</allowDelete>
    <allowEdit>true</allowEdit>
    <allowRead>true</allowRead>
    <viewAllRecords>false</viewAllRecords>
    <modifyAllRecords>false</modifyAllRecords>
    <object>MyNamespace__JobRequest__c</object>
</objectPermissions>

要检索:

<types>
    <members>MyNamespace__JobRequest__c</members>
    <name>CustomObject</name>
</types>
<types>
    <members>MyProfile</members>
    <name>Profile</name>
</types>

检索权限集和配置文件时,请确保还检索任何 与权限和设置相关的组件。例如,当 检索应用程序可见性时,还必须检索关联的应用程序,以及何时检索 检索对象或字段权限时,还必须检索关联的 对象。

在部署中运行测试

生产环境中的默认测试执行

如果部署选项中未指定测试级别,则 默认测试执行行为取决于部署包的内容。什么时候 部署到生产环境后,除源自托管包的测试外,所有测试都是 如果您的部署包包含 Apex 类或触发器,则执行。如果您的包裹 不包含 Apex 组件,默认情况下不运行任何测试。

在 API 版本 33.0 及更早版本中,对以下组件运行了测试 所需的测试,例如自定义对象,而不仅仅是针对 Apex 组件。例如,如果 您的包包含一个自定义对象,所有测试都在 API 版本 33.0 及更早版本中运行。在 相比之下,从 API 版本 34.0 开始,不会对此包运行任何测试。API 版本 对应于 API 客户端的版本或您正在使用的工具的版本(Ant 迁移工具)。

您可以为非 Apex 组件的部署运行测试。您可以 通过在部署中设置测试级别来替代默认测试执行行为 选项。无论 部署包。我们建议您在开发中运行所有本地测试 环境,例如沙盒,然后再部署到生产环境。在 开发环境减少了在生产环境中运行所需的测试数量 部署。

API 版本 33.0 及更早版本的生产环境中的默认测试执行

若要部署到生产组织,将运行组织中的所有本地测试 默认情况下。默认情况下,源自已安装的托管包的测试不会运行。如果 任何测试失败,整个部署都将回滚。

如果部署包含以下元数据类型的组件,则所有本地测试都是 跑。

  • 顶点类
  • Apex组件
  • ApexPage(顶点页面)
  • Apex触发器
  • 文章类型
  • BaseSharingRule
  • CriteriaBasedSharingRule
  • 自定义字段
  • 自定义对象
  • 数据类别组
  • 已安装的软件包
  • NamedFilter(名称过滤器)
  • OwnerSharingRule
  • 权限集
  • 轮廓
  • 队列
  • 记录类型
  • RemoteSiteSetting
  • 角色
  • 共享原因
  • 领土
  • 验证规则
  • 工作流程

例如,不会对以下部署运行任何测试:

  • 1 CustomApplication 组件
  • 100 个报表组件和 40 个仪表板组件

但是,所有本地测试都针对以下任何示例部署运行,因为它们 包括上面列表中的至少一个组件:

  • 1 CustomField 组件
  • 1 个 ApexComponent 组件和 1 个 ApexClass 组件
  • 5 个 CustomField 组件和 1 个 ApexPage 组件
  • 100 个报表组件、40 个仪表板组件和 1 个 CustomField 组件

在部署中运行测试的子集

测试级别使你能够更好地控制在部署中运行哪些测试。自 缩短部署到生产的时间,在部署 Apex 组件时运行测试子集。这 生产环境中的默认测试执行行为也已更改。默认情况下,如果没有测试级别 指定时,不会执行任何测试,除非您的部署包包含 Apex 类或 触发器。

如果部署中某个 Apex 组件的代码覆盖率小于 75%,则部署 失败。如果指定的测试之一失败,则部署也会失败。我们建议您测试 首先在沙盒中部署,以确保指定的测试涵盖每个组件 充分。即使组织的整体代码覆盖率为 75% 或更高,个人 正在部署的 Apex 组件的覆盖范围可能较小。如果代码覆盖率要求 不满足,编写更多测试并将它们包含在部署中。

若要运行测试的子集,请设置测试 对象的级别。接下来,指定每个测试 要在 中运行的类。最后,作为参数传递给调用。以下示例执行这些步骤以仅运行指定的 测试类。RunSpecifiedTestsDeployOptionsDeployOptionsDeployOptionsdeploy()

// Create the DeployOptions object.
DeployOptions deployOptions = new DeployOptions();

// Set the appropriate test level.
deployOptions.setTestLevel(TestLevel.RunSpecifiedTests);

// Specify the test classes to run.
// String array contains test class names.
String[] tests = {"TestClass1", "TestClass2", "TestClass3"};
// Add the test class names array to the deployment options.
deployOptions.setRunTests(tests);

// Call deploy() by passing the deployment options object as an argument. 
AsyncResult asyncResult = metadatabinding.deploy(zipBytes,deployOptions);

有关运行特定测试的注意事项

  • 您只能指定测试类。不能指定单个测试方法。
  • 我们建议您重构测试类,以包含满足的最小测试数 代码覆盖率要求。重构测试类有助于缩短测试时间 执行时间,从而缩短部署时间。
  • 您可以通过使用非活动状态部署目标组织中的触发器来停用该触发器 州。但是,触发器必须以前已部署为活动状态。

在沙盒和生产部署中运行相同的测试

从 API 版本 34.0 开始,您可以选择在开发中运行哪些测试 环境,例如仅本地测试,以匹配在生产环境中运行的测试。在早期版本中, 如果在沙盒部署中启用了测试,则无法排除托管包 测试。

默认情况下,在部署到非生产组织(例如 沙盒或 Developer Edition 组织。指定要在开发中运行的测试 环境,设置 testLevel 部署 选项。例如,在部署中运行本地测试并排除托管包 tests,将对象上的 testLevel 设置为 。 接下来,将此对象作为参数传递给调用 如下。DeployOptionsTestLevel.RunLocalTestsdeploy()

// Create the DeployOptions object.
DeployOptions deployOptions = new DeployOptions();

// Set the appropriate test level.
deployOptions.setTestLevel(TestLevel.RunLocalTests);

// Call deploy() by passing the deployment options object as an argument. 
AsyncResult asyncResult = metadatabinding.deploy(zipBytes,deployOptions);

注意

无论 部署包的内容。相比之下,默认情况下,测试在生产环境中执行 仅当您的部署包包含 Apex 类或触发器时。可用于沙盒和生产部署。RunLocalTestsRunLocalTests

维护用户引用

在元数据部署期间保留用户字段。

当部署中的组件 指特定用户,例如工作流电子邮件的收件人 通知或仪表板运行用户,然后 Salesforce 尝试 通过比较在目标组织中查找匹配的用户 部署期间的用户名。

例如,当您将数据复制到沙盒时,包含来自生产组织的用户名的字段 更改为包含沙盒名称。在名为 的沙盒中,用户名变为 。当您部署 沙盒中的元数据,则用户名中的元数据将被忽略。testuser@acme.comuser@acme.com.testtest对于部署中的用户引用,Salesforce 执行 顺序如下:

  1. Salesforce 将源环境中的用户名与目标环境中的用户名进行比较 环境并调整组织域名。
  2. 如果两个或多个用户名匹配,Salesforce 会列出 匹配的名称和请求源环境中的一个用户 重命名。
  3. 如果源环境中的用户名不存在 目标环境,Salesforce 显示 错误,部署将停止,直到删除用户名 或解析为目标环境中的用户。

基于 CRUD 的元数据开发

使用基于 CRUD 的元数据调用创建、更新或删除设置和 组织或应用程序的配置组件。这些配置 组件包括自定义对象、自定义字段和其他配置元数据。这 元数据调用模仿 Salesforce 用户界面中用于创建、更新、 或删除组件。无论那里适用什么规则,也适用于这些调用。

元数据调用在这些方面与核心同步 API 调用不同。

  • 元数据 API 调用在单独的 WSDL 中可用。自 下载 WSDL,登录 Salesforce,从“设置”中,输入“快速查找”框,然后 选择 API,然后单击 Download Metadata WSDL 链接。API
  • 登录后,您必须将元数据 API 调用发送到元数据 API 端点。 其 URL 与 SOAP API 不同。从 返回的 LoginResult 中检索 metadataServerUrl SOAP API 调用。更多信息 关于 SOAP API,请参阅 SOAP API 开发人员 指南。login()
  • 元数据调用可以是同步的,也可以是异步的。CRUD 调用在 API 版本 30.0 及更高版本,与 API 核心调用类似,结果如下 在一次调用中返回。在早期 API 版本中,创建、更新和删除 只是异步的,这意味着结果不会立即返回 在一次通话中。
  • 有映射到相应核心 SOAP API 的同步元数据调用 同步调用。
    • createMetadata() 映射到 SOAP API 调用。create()
    • updateMetadata() 映射到 SOAP API 调用。update()
    • deleteMetadata() 映射到 SOAP API 调用。delete()

注意

元数据 API 还支持和调用检索和部署元数据 组件。有关更多信息,请参阅部署和检索元数据。retrieve()deploy()

使用同步调用进行基于 CRUD 的开发 Java 示例

本节将指导您完成使用基于 CRUD 的示例 Java 客户端应用程序 调用。此示例应用程序执行以下主要任务。

  1. 使用该类 创建元数据连接。有关更多信息,请参阅步骤 3:演练 Java 示例代码。MetadataLoginUtil.java
  2. 调用 createMetadata() 以创建自定义 对象。此调用在一次调用中返回结果。
  3. 将返回的对象检查到 检查操作是否成功,如果没有成功,则写入组件名称, 错误消息和状态代码。SaveResult
import com.sforce.soap.metadata.*;

/**
 * Sample that logs in and creates a custom object through the metadata API
 */
public class CRUDSampleCreate {
    private MetadataConnection metadataConnection;

    // one second in milliseconds
    private static final long ONE_SECOND = 1000;

    public CRUDSampleCreate() {
    }

    public static void main(String[] args) throws Exception {
        CRUDSampleCreate crudSample = new CRUDSampleCreate();
        crudSample.runCreate();
    }

    /**
     * Create a custom object. This method demonstrates usage of the
     * create() and checkStatus() calls.
     *
     * @param uniqueName Custom object name should be unique.
     */
    private void createCustomObjectSync(final String uniqueName) throws Exception {
        final String label = "My Custom Object";
        CustomObject co = new CustomObject();
        co.setFullName(uniqueName);
        co.setDeploymentStatus(DeploymentStatus.Deployed);
        co.setDescription("Created by the Metadata API Sample");
        co.setEnableActivities(true);
        co.setLabel(label);
        co.setPluralLabel(label + "s");
        co.setSharingModel(SharingModel.ReadWrite);

        // The name field appears in page layouts, related lists, and elsewhere.
        CustomField nf = new CustomField();
        nf.setType(FieldType.Text);
        nf.setDescription("The custom object identifier on page layouts, related lists etc");
        nf.setLabel(label);
        nf.setFullName(uniqueName);
        customObject.setNameField(nf);

        SaveResult[] results = metadataConnection
                .createMetadata(new Metadata[] { co });

        for (SaveResult r : results) {
            if (r.isSuccess()) {
                System.out.println("Created component: " + r.getFullName());
            } else {
                System.out
                        .println("Errors were encountered while creating "
                                + r.getFullName());
                for (Error e : r.getErrors()) {
                    System.out.println("Error message: " + e.getMessage());
                    System.out.println("Status code: " + e.getStatusCode());
                }
            }
        }
    }

    private void runCreate() throws Exception {
        metadataConnection = MetadataLoginUtil.login();
        // Custom objects and fields must have __c suffix in the full name.
        final String uniqueObjectName = "MyCustomObject__c";
        createCustomObjectSync(uniqueObjectName);
    }
}

使用异步调用进行基于 CRUD 的开发的 Java 示例

重要

本节中的示例取决于异步 CRUD 调用。异步 CRUD 调用是 no 从 API 版本 31.0 开始提供更长的时间,并且仅在早期 API 中可用 版本。create()

本节将指导您完成一个示例 Java 客户端应用程序,该应用程序使用 基于 CRUD 的异步调用。此示例应用程序执行以下主要操作 任务:

  1. 使用该类 创建元数据连接。有关更多信息,请参阅步骤 3:演练 Java 示例代码。MetadataLoginUtil.java
  2. 调用 create() 来创建一个 自定义对象。Salesforce 返回 的 AsyncResult 对象 您尝试创建的每个组件。AsyncResult 对象是 当操作从队列移动到 “已完成”或“错误”状态。
  3. 在循环中调用 checkStatus() 直到 AsyncResult 中的 status 值指示创建操作已完成。

请注意每个 API 调用后面的错误处理代码。

import com.sforce.soap.metadata.*;

/**
 * Sample that logs in and creates a custom object through the metadata api
 */
public class CRUDSample {
    private MetadataConnection metadataConnection;

    // one second in milliseconds
    private static final long ONE_SECOND = 1000;

    public CRUDSample() {
    }

    public static void main(String[] args) throws Exception {
        CRUDSample crudSample = new CRUDSample();
        crudSample.runCreate();
    }

    /**
     * Create a custom object. This method demonstrates usage of the
     * create() and checkStatus() calls.
     *
     * @param uniqueName Custom object name should be unique.
     */
    private void createCustomObject(final String uniqueName) throws Exception {
        final String label = "My Custom Object";
        CustomObject customObject = new CustomObject();
        customObject.setFullName(uniqueName);
        customObject.setDeploymentStatus(DeploymentStatus.Deployed);
        customObject.setDescription("Created by the Metadata API Sample");
        customObject.setLabel(label);
        customObject.setPluralLabel(label + "s");
        customObject.setSharingModel(SharingModel.ReadWrite);

        // The name field appears in page layouts, related lists, and elsewhere.
        CustomField nf = new CustomField();
        nf.setType(FieldType.Text);
        nf.setDescription("The custom object identifier on page layouts, related lists etc");
        nf.setLabel(label);
        nf.setFullName(uniqueName);
        customObject.setNameField(nf);

        AsyncResult[] asyncResults = metadataConnection.create(
            new CustomObject[]{customObject});
        if (asyncResults == null) {
            System.out.println("The object was not created successfully");
            return;
        }

        long waitTimeMilliSecs = ONE_SECOND;

        // After the create() call completes, we must poll the results of the checkStatus()
        // call until it indicates that the create operation has completed.
        do {
            printAsyncResultStatus(asyncResults);
            waitTimeMilliSecs *= 2;
            Thread.sleep(waitTimeMilliSecs);
            asyncResults = metadataConnection.checkStatus(new String[]{asyncResults[0].getId()});
        } while (!asyncResults[0].isDone());

        printAsyncResultStatus(asyncResults);
    }

    private void printAsyncResultStatus(AsyncResult[] asyncResults) throws Exception {
        if (asyncResults == null || asyncResults.length == 0 || asyncResults[0] == null) {
            throw new Exception("The object status cannot be retrieved");
        }

        AsyncResult asyncResult = asyncResults[0]; //we are creating only 1 metadata object

        if (asyncResult.getStatusCode() != null) {
            System.out.println("Error status code: " +
                    asyncResult.getStatusCode());
            System.out.println("Error message: " + asyncResult.getMessage());
        }

        System.out.println("Object with id:" + asyncResult.getId() + " is " +
            asyncResult.getState());
    }

    private void runCreate() throws Exception {
        metadataConnection = MetadataLoginUtil.login();
        // Custom objects and fields must have __c suffix in the full name.
        final String uniqueObjectName = "MyCustomObject__c";
        createCustomObject(uniqueObjectName);
    }
}

REST 资源

使用 REST 资源进行移动 Salesforce 组织与本地文件系统之间的元数据(XML 文件)。

deployRequest

XML 文件中的数据使用英语(美国)区域设置进行格式设置。这种方法 确保对依赖于区域设置的字段(如日期字段)的解释一致 在使用不同语言的组织之间进行数据迁移期间。组织可以 支持多种语言向用户展示。

元数据部署主要用于以下开发方案。

  • 在沙盒组织中开发自定义应用程序(或自定义)。后 完成开发和测试,然后部署应用程序或自定义项 使用元数据 API 进入生产组织。
  • 在 Developer Edition 组织中对应用程序进行团队开发。开发后 并完成测试,然后您可以通过 Lightning Platform 分发应用程序 AppExchange。

使用 Zip 文件

该资源用于部署 .zip 文件。在 .zip 文件中有一个项目清单 (package.xml) 列出要检索或部署的内容,以及组织到其中的一个或多个 XML 组件 文件夹。deployRequest

注意

组件是 元数据类型。 例如,是自定义对象的元数据类型,组件是 自定义对象的实例。CustomObjectMyCustomObject__c

部署在 .zip 文件中的文件可以解压缩 驻留在组织中的组件(例如标准对象)。这 文件也可以是驻留在命名包中的打包组件。

注意

一次最多可以部署 10,000 个文件。(在 API 版本 43.0 中 及更高版本,AppExchange 软件包最多可以包含 12,500 个文件。.zip 文件大小限制 适用于 SOAP 调用的不适用于 REST 资源。但是,400 MB 的组件限制 上传后解压缩到解压缩的文件夹中适用于 SOAP 和 REST 部署。deployRequest

每个 .zip 文件都包含一个项目清单、一个名为 package.xml 的文件以及一组包含组件的目录。 清单文件定义您尝试检索或部署的组件,以及 用于部署或检索的 API 版本。

下面是一个示例包 .xml 文件。

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MyCustomObject__c</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>Standard</members>
        <name>Profile</name>
    </types>
    <version>59.0</version>
</Package>

可以在 package.xml 中定义以下元素。

  • <fullName>包含服务器端的名称 包。如果不存在,则它是客户端包。<fullName>unpackaged
  • <types>包含元数据类型的名称(对于 示例, ) 和命名成员 (对于 示例,) 进行部署。您可以在清单中添加多个元素 文件。CustomObjectmyCustomObject__c<types>
  • <members>包含组件的 fullName,例如 。对于许多元数据类型,可以将 中的值替换为通配符(星号),而不是单独列出每个成员。为 允许通配符的元数据类型列表,请参阅“允许 “元数据类型”中的通配符 (*)?“ 列。MyCustomObject__cmembers*注意在元素中指定 Security,在名称中指定 Settings 元素。<members>
  • <name>包含元数据类型,例如 或 。目录中的每种元数据类型都定义了一个名称。任何 扩展元数据的元数据类型是 有效值。输入的名称必须与 元数据 API WSDL。有关列表,请参阅元数据类型。CustomObjectProfile
  • <version>是使用的 API 版本号 部署或检索 .zip 文件时。目前 有效值为 。59.0

有关演示如何工作的更多示例包 .xml 清单文件 使用不同的元数据子集,请参阅示例包 .xml 清单 文件。

要删除组件,请参阅从组织中删除组件。

使用 REST 通过 Apex 测试部署元数据

使用 REST 资源部署到 启动处理部署的所有操作的请求。

deployRequest

您可以部署或 一次最多可检索 10,000 个文件。AppExchange 软件包使用不同的限制: 最多可包含 35,000 个文件。已部署或检索的 .zip 的最大大小 文件大小为 39 MB。如果文件在解压缩的文件夹中解压缩,则大小限制 是 400 MB。URIhttps://host/services/data/vXX.0/metadata/deployRequest格式JSON格式HTTP 方法发布认证Authorization: Bearer token

deployOptions 参数

注意

查看可以节省时间的部署和方法的默认测试行为 同时仍使您能够满足测试要求,请参阅在部署中运行测试和在沙盒和生产部署中运行相同的测试。

参数描述
allowMissingFiles布尔。如果 package.xml 中指定的文件不是 在 .zip 文件中,指定部署是否仍可 成功。不要为部署到生产组织设置此参数。
autoUpdatePackage保留以备将来使用。
仅检查布尔。缺省值为 .设置为执行 组件,而不将组件保存在目标组织中。验证使您能够 验证将在部署中生成但未生成的测试结果 提交任何更改。验证完成并通过测试后,它就可以符合条件 用于在不重新运行测试的情况下进行部署。请参阅在不进行测试的情况下部署最近验证的组件集。falsetrue
ignore警告布尔。指示部署是否 尽管有一个或多个警告 () 或不 (),但允许成功完成。缺省值为 .truefalsefalse的 DeployMessage 对象 warning 包含以下值:问题类型—Warningproblem – 警告的文本。如果出现警告,并且 ignoreWarnings 设置为 ,则 success 字段 在 DeployMessage 中是 。如果 ignoreWarnings 设置为 ,则 success 设置为 ,并且警告被视为 错误。truetruefalsefalse
执行检索保留以备将来使用。
purgeOnDelete(清除OnDelete)布尔。如果 ,destructiveChanges.xml 清单文件中已删除的组件不会存储在 回收站。相反,它们会立即符合删除条件。true此选项仅适用于 Developer Edition 或沙盒组织。 它在生产组织中不起作用。
rollbackOnError布尔。指示任何故障是否会导致完全回滚 () 或 ()。如果,无论什么动作都可以 在不执行错误的情况下执行,并返回其余的错误 行动。此参数必须设置为 if 您正在部署到生产组织。缺省值为 。truefalsefalsetruefalse
运行测试字符串 []。要在部署期间运行的 Apex 测试列表。指定类 name,每个实例一个名称。类名还可以指定带有点的命名空间 表示法。有关更多信息,请参见在部署中运行测试的子集。要使用此选项,请将 testLevel 设置为 。RunSpecifiedTests
单包布尔。指示指定的文件是指向具有单个包 () 的目录结构,还是指向一组包 (..ziptruefalse)
testLevelTestLevel(字符串类型的枚举)。自选。指定运行哪些测试 作为部署的一部分。无论类型如何,都会强制执行测试级别 部署包中存在的组件。有效值为:NoTestRun– 不运行任何测试。这 测试级别仅适用于开发环境的部署,例如 沙盒、Developer Edition 或试用组织。此测试级别是 开发环境的默认值。RunSpecifiedTests– 仅运行您在 runTests 选项中指定的测试。代码覆盖率要求 使用此测试级别时,与默认覆盖率要求不同。每 部署包中的类和触发器必须被执行的 测试至少 75% 的代码覆盖率。此覆盖范围是针对每个 类和触发器单独,与整体覆盖范围不同 百分比。RunLocalTests—所有测试在您的 org 运行,但源自 installed managed 和 解锁的包裹。此测试级别是生产环境的默认级别 包含 Apex 类或触发器的部署。RunAllTestsInOrg—所有测试都是 跑。这些测试包括组织中的所有测试,包括托管测试 包。如果未指定测试级别,则默认测试执行行为为 使用。请参阅在部署中运行测试。作为部署的一部分运行的 Apex 测试始终以同步和串行方式运行。

请求正文:部署元数据

部署元数据时,请求包括部署参数和 .zip 包含组件目录和清单的文件。将标头设置为 ,Content-Type: multipart/form-data

此示例 POST 请求创建一个启动部署的对象。deployRequest

  1. POST 请求标头设置为并定义一个值来封装请求的不同子部分。Content-Type: multipart/form-databoundary
  2. 在第一个边界之后的子部分中,JSON 请求创建一个子对象,用于传递部署参数。deployOptions
  3. 第二个边界后面的子部分指定包含清单的 .zip 文件 和组件目录。
POST /services/data/v48.0/metadata/deployRequest
Authorization: Bearer 00D....
Content-Type: multipart/form-data; boundary=--------------------------BOUNDARY
----------------------------BOUNDARY
Content-Disposition: form-data; name="json"
Content-Type: application/json
{ 
    "deployOptions" :
        {
        "allowMissingFiles" : false,
        "autoUpdatePackage" : false,
        "checkOnly" : false,
        "ignoreWarnings" : false,
        "performRetrieve" : false,
        "purgeOnDelete" : false,
        "rollbackOnError" : false,
        "runTests" : null,
        "singlePackage" : true,
        "testLevel" : "RunAllTestsInOrg"
        }
    }
----------------------------BOUNDARY
Content-Disposition: form-data; name="file"; filename="deploy.zip"
Content-Type: application/zip

//Contents of deploy.zip
----------------------------BOUNDARY--

响应正文:部署元数据

当返回 HTTP 状态码 (Created) 时,您的 请求已成功,并导致创建正在处理的部署。201

{ "id" : "0Afxx00000001VPCAY",
  "deployOptions" : 
   { "checkOnly" : false,
     "singlePackage" : false,
     "allowMissingFiles" : false,
     "performRetrieve" : false,
     "autoUpdatePackage" : false,
     "rollbackOnError" : true,
     "ignoreWarnings" : false,
     "purgeOnDelete" : false,
     "runAllTests" : false },
  "deployResult" : 
   { "id" : "0Afxx00000001VPCAY",
     "success" : false,
     "checkOnly" : false,
     "ignoreWarnings" : false,
     "rollbackOnError" : true,
     "status" : "Pending",
     "runTestsEnabled" : false,
     "done" : false } }

deployResult 参数

参数描述
编号ID。正在部署的组件的 ID。
canceled作者ID。取消部署的用户的 ID。
canceledByName字符串。取消部署的用户的全名。
仅检查布尔。指示此部署是否用于检查 在不更改组织的情况下部署的文件 () 或不 ()。仅检查部署不会 部署任何组件或以任何方式更改组织。truefalse
完成日期日期时间。部署过程结束的时间戳。
创建者ID。创建部署的用户的 ID。
createdByName字符串。创建部署的用户的全名。
创建日期日期时间。收到部署请求时的时间戳。
DeployDetails。提供正在进行的部署的详细信息,或者 ended if 添加为 查询到 GET 请求。?includeDetails=true
布尔。指示服务器是否完成了部署请求的处理 对于指定的 ID。
errorMessage (错误消息)字符串。与 errorStatusCode 字段中的值(如果有)相对应的消息。
errorStatusCode字符串。如果在部署请求期间发生错误,则状态代码为 返回,在 errorMessage字段中返回状态码对应的消息。
ignore警告布尔。自选。缺省值为 . 指定即使部署生成警告,部署是否继续。 不要将此参数设置为 for deployments 到生产组织。falsetrue
上一个修改日期日期时间。部署过程上次更新的时间戳。
numberComponentErrors国际部署过程中部署的组件数。使用这个 value 替换为 numberComponentsTotal 值来获取估计值 部署进度。
numberComponentsTotal(数量组件合计)国际部署中的组件总数。将此值与 numberComponentsDeployed 值一起使用可获取 部署进度。
numberTestErrors国际在此期间生成错误的 Apex 测试数 部署。
numberTests已完成此部署已完成的 Apex 测试数。将此值与 numberTestsTotal 值一起使用,可获取部署的 测试进度。
numberTestsTotal国际此部署的 Apex 测试总数。将此值用于 numberTestsCompleted 值来获取 部署的测试进度。此字段中的值在 部署已开始对正在部署的组件运行测试。
runTests已启用布尔。指示 Apex 测试是否作为此部署的一部分运行 () 或不 ()。测试要么作为部署的一部分自动运行,要么 可以设置为在 deployOptions 子对象中运行。truefalse
rollbackOnError布尔。缺省值为 .表明 是否有任何故障导致完全回滚 () 或不 ()。如果 ,可以执行任何一组操作 不执行任何错误,其余操作返回错误。 如果 部署到生产组织。truetruefalsefalsetrue
开始日期日期时间。部署过程开始的时间戳。
状态详细信息字符串。指示正在部署哪个组件或哪个 Apex 测试类 运行。
地位指示部署的当前状态。有效值为:PendingInProgressSucceededSucceededPartialFailedCancelingCanceled
成功布尔。指示部署是否成功 () 或 ()。truefalse

使用 REST 资源检查部署状态

检查部署状态,方法是在 URL 响应正文与原始部署请求返回的响应正文类似,但它 包括有关正在进行的部署的信息。URIhttps://host/services/data/vXX.0/metadata/deployRequest/deployRequestId

自 在响应中包含更多详细信息,请使用:

https://host/services/data/vXX.0/metadata/deployRequest/deployRequestId?includeDetails=true格式JSON格式HTTP 方法获取认证Authorization: Bearer token

响应正文:部署元数据

以下示例显示了作为查询添加到 GET 请求时的响应。?includeDetails=true

{ 
	       "id" : "0Afxx00000000lWCAQ"
	       "url" : "https://host/services/data/vXX.0/metadata/deployRequest/0Afxx00000000lWCAQ?includeDetails=true",
        "deployResult" :
            {
            "checkOnly" : "false",
            "ignoreWarnings" : "false",
            "rollbackOnError" : "false",
            
            "status : "InProgress",
            "numberComponentsDeployed" : "10", 
            "numberComponentsTotal" : "1032",
            "numberComponentErrors" : "0",
            "numberTestsCompleted" : "45",
            "numberTestsTotal" : "135",
            "numberTestErrors" : "0",            
            "details" :  { 
	             "componentFailures" : [],
             	"componentSuccesses" : [],
                    "retrieveResult" : null,
                    "runTestResults" : {
                    "numRun" : 0,
                    "successes" : [ … ],
                    "failures" : []
	         	         }
            },

            "createdDate" : "2017-10-10T08:22Z",       
            "startDate" : "2017-10-10T08:22Z",
            "lastModifiedDate" : "2017-10-10T08:44Z",
            "completedDate" : "2017-10-10T08:44Z",

            "errorStatusCode" : null,
            "errorMessage" : null,
            "stateDetail" : "Processing Type: Apex Component",

            "createdBy" : "005xx0000001Sv1m",
            "createdByName" : "stephanie stevens", 
            "canceledBy" : null,
            "canceledByName" : null,            
            "isRunTestsEnabled" : null
            }

       "deployOptions": {    
             "allowMissingFiles" : false,
             "autoUpdatePackage" : false,
             "checkOnly" : true,
             "ignoreWarnings" : false,
             "performRetrieve" : false,
             "purgeOnDelete" : false,
             "rollbackOnError" : false,
             "runTests" : null,
             "singlePackage" : true,
             "testLevel" : "RunAllTestsInOrg"
             }
     }

预计返回 HTTP 状态代码 (OK)。200

部署最近验证的组件集,无需测试

您可以通过跳过 Apex 的执行,在更短的时间内将组件部署到生产环境 在已经满足测试要求时进行测试。

  • 在过去 10 年中,这些组件已针对目标环境成功验证 日。
  • 作为验证的一部分,目标组织中的 Apex 测试已通过。
  • 满足代码覆盖率要求。
    • 如果运行组织中的所有测试或所有本地测试,则总体代码覆盖率至少为 75%, 和 Apex 触发器有一定的覆盖范围。
    • 如果使用测试级别运行特定测试,则至少覆盖了 75% 的要部署的每个类和触发器 单独。RunSpecifiedTests

此操作等效于在 Salesforce 用户界面中的“部署状态”页面。

要在使用资源时验证但不部署一组组件,请将参数设置为 。记下响应中的部署请求 ID。使用此 ID (与成功的验证相关联)以部署组件集,而无需重复 验证。deployRequestcheckOnlydeployOptionstrueURIhttps://host/services/data/vXX.0/metadata/deployRequest/validatedDeployRequestId格式JSON格式HTTP 方法发布认证Authorization: Bearer token

请求正文:部署最近验证的组件集,无需测试

注意

用于部署最近验证的组件集的 HTTP 方法是 POST,而不是 PATCH。用 PATCH 将创建一个新部署。

{ 
       "validatedDeployRequestId" : "0Afxx00000000lWCAQ"
    }

如果没有满足验证要求的相应部署包,则 接收 HTTP 状态代码 (Not Found)。如果已验证 找到部署包,返回的 HTTP 状态码为 (Created)。404201

响应正文:部署最近验证的组件集,而不进行测试

注意

来自未验证请求的部署的响应正文包括新的请求 ID。 因为它与之前对仅验证部署的请求是分开的。

{ 
       "validatedDeployRequestId" : "0Afxx00000000lWCAQ"
       "id" : "0Afxx00000000lWMEM"
       "url" : "https://host/services/data/vXX.0/metadata/deployRequest/0Afxx00000000lWMEM",
       "deployOptions" :
             {
             "allowMissingFiles" : false,
             "autoUpdatePackage" : false,
             "checkOnly" : true,
             "ignoreWarnings" : false,
             "performRetrieve" : false,
             "purgeOnDelete" : false,
             "rollbackOnError" : false,
             "runTests" : null,
             "singlePackage" : true,
             "testLevel" : "RunAllTestsInOrg"
}
     }

当返回 HTTP 状态码 (Created) 时,您的 请求已成功,并导致创建正在处理的部署。在 在前面的示例响应正文中,仅验证部署请求的 ID 为 ;部署的 ID,不带 验证请求是 。2010Afxx00000000lWCAQ0Afxx00000000lWMEM

使用 REST 取消正在进行的部署

您可以请求取消正在进行的部署。使 通过修补正在进行的 .取消是异步处理的。

deployRequestURIhttps://host/services/data/vXX.0/metadata/deployRequest/deployRequestId格式JSON格式HTTP 方法补丁认证Authorization: Bearer token

请求正文:请求部署取消

部署取消的 JSON 请求正文包括 源语言。deployRequest

{ 
     "deployResult":
           {
           "status" : "Canceling"
           }
    }

响应正文:请求部署取消

由于取消请求是异步处理的,因此响应中显示的状态 body 可以是 或 。CancelingCanceled

{ 
      	"id" : "0Afxx00000000lWCAQ"
      	"url" : “https://host/services/data/vXX.0/metadata/deployRequest/0Afxx00000000lWCAQ",
       "deployResult":    
             {
             "checkOnly" : "false",
             "ignoreWarnings" : "false",
             "rollbackOnError" : "false",             
             "status : "Canceling",  // or Canceled
             "numberComponentsDeployed" : "10",
             "numberComponentsTotal" : "1032",
             "numberComponentErrors" : "0",
             "numberTestsCompleted" : "45",
             "numberTestsTotal" : "135",
             "numberTestErrors" : "0",
             "details" :  { 
                "componentFailures" : [],
                "componentSuccesses" : [],
                      "retrieveResult" : null,
                      "runTestResults” : {
                         "numRun" : 0,
                         "successes" : [ … ],
                         "failures" : []
                 	   	}             
                },

                "createdDate" : "2017-10-10T08:22Z",
                "startDate" : "2017-10-10T08:22Z",
                "lastModifiedDate" : "2017-10-10T08:44Z",
                "completedDate" : "2017-10-10T08:44Z",
                "errorStatusCode" : null,
                "errorMessage" : null,
                "stateDetail" : "Processing Type: Apex Component",
                "createdBy" : "005xx0000001Sv1m",
                "createdByName" : "steve stevens",
                "canceledBy" : null, 
                "canceledByName" : null,
                "isRunTestsEnabled" : null
                }
       }

当返回 HTTP 状态码 (Accepted) 时,您的 取消请求正在进行中或成功。202

在 Salesforce CLI 中使用 REST API 部署元数据

默认情况下,Salesforce CLI 命令使用元数据 SOAP API 将源部署到您的组织。您可以 通过设置 CLI 配置值或环境来改用元数据 REST API 变量。与 SOAP API 相比,REST API 提供了更快的部署速度。

project deploy start

用户 所需权限
要从 Salesforce CLI 使用元数据 API,请执行以下操作:通过元数据 API 函数修改元数据或修改所有数据

使用 Salesforce CLI 运行时配置变量或环境变量,用于将 REST API 设置为 默认值。有关更多信息,请参阅《Salesforce DX 设置指南》。org-metadata-rest-deploySF_ORG_METADATA_REST_DEPLOY

此示例使用配置值来设置当前 项目:

sf config set org-metadata-rest-deploy true

若要为所有项目全局设置默认值,请使用以下标志:–global

sf config set org-metadata-rest-deploy true --global

注意

仅部署源的命令,例如 project deploy start,支持 REST API。检索源的命令(如项目检索启动)始终使用 SOAP API。

以下是部署限制。

特征限制
最大压缩 .zip 文件夹大小1(SOAP API)约39MB
最大未压缩文件夹大小2(SOAP API)约400MB
AppExchange 软件包(REST 和 SOAP)中的最大文件数 API接口)30,000(API 版本 47.0 及更高版本)22,000(API 版本 46.0)17,500(API 版本 45.0)12,500(API 版本 43.0 和 44.0)10,000(API 版本 42.0 及更早版本)
包中的最大文件数(REST 和 SOAP API)10,000

1元数据 API base-64 在压缩组件后对其进行编码。这 生成的 .zip 文件不能超过 50 MB。Base-64 编码增加了 有效负载大约减少 22%,因此压缩的有效负载不能超过大约 编码前为 39 MB。

2使用 Ant 迁移工具部署解压项目时,所有 首先压缩项目中的文件。未压缩的最大大小 未压缩项目中的组件为 400 MB 或更少,具体取决于文件的 压缩比。如果文件的压缩率较高,则可以将 总计约为 400 MB,因为压缩大小将小于 39 MB。 但是,如果组件不能被压缩太多,比如二进制静态资源, 您可以迁移小于 400 MB。

错误处理

元数据 API 调用返回客户端应用程序的错误信息 可用于识别和解决运行时错误。

元数据 API 提供这些类型的错误处理。

  • 由于元数据 API 使用企业或合作伙伴 WSDL 进行身份验证,因此它使用 SOAP 错误 在这些 WSDL 中为格式不正确的消息导致的错误定义的消息, 身份验证失败或类似问题。每个 SOAP 错误都有一个关联的 ExceptionCode。有关详细信息,请参阅《SOAP API 开发人员指南》中的错误处理。
  • 对于异步 create()、update() 和 delete() 调用的错误, 请参阅关联组件的 AsyncResult 对象的 statusCode 字段中的错误状态代码。
  • 有关同步 CRUD 调用的错误,请参阅 Error 对象的 statusCode 字段中的错误状态代码 对应于相应结果对象的 errors 字段返回的数组中的每个错误。例如,createMetadata() 的结果对象是 SaveResult。
  • 对于 deploy() 的错误,请参阅 关联的 DeployMessage 对象中的问题和成功字段 元件。
  • 对于 retrieve() 的错误, 请参阅 RetrieveMessage 对象中的问题字段 对于关联的组件。

有关示例代码,请参阅步骤 3:演练 Java 示例代码。

会话过期的错误处理

当您通过通话登录时,新的客户端会话 开始,并生成相应的唯一会话 ID。会话在以下时间后自动过期 在 Salesforce 应用程序的“Security Controls”设置区域中指定的时间量(默认为 2 小时)。 会话过期时,将返回异常代码INVALID_SESSION_ID。如果发生这种情况, 您必须再次调用该调用。更多信息 关于,请参阅《SOAP API 开发人员指南》。login()login()login()

快速入门:元数据 API

面向初学者开发人员的资源

如果您是初学者开发人员,并且以前没有使用过 Salesforce CLI,请了解如何设置 您的环境和示例应用程序的实践。这些 Trailhead 将引导您完成 使用 SFDX 进行设置,并向您介绍元数据 API。

使用 Salesforce CLI 和源代码管理开发应用程序 登山口

演练使用以下方法设置环境和使用 Salesforce CLI 进行开发 Dreamhouse 示例应用。向 Dreamhouse 应用程序添加功能后,将元数据部署到 使用 Salesforce CLI 的 Dev Hub 组织。

包 .xml 元数据管理

详细了解元数据和包.xml文件。生成包.xml文件以部署更改 从零开始的组织到您的 Trailhead Playground。

使用元数据 API 进行开发的快速入门

如果您在 Salesforce 开发方面有一些经验,但想开始使用元数据 API,请使用此快速入门。本快速入门将引导您完成元数据的检索 组件,这是开发过程的第一步。

  1. 先决条件 在开始使用元数据 API 进行开发之前
    ,请完成这些先决条件。
  2. 步骤 1:(可选)使用 UI
    将元数据组件添加到组织 如果您从没有自定义项的新实践组织开始,则只有无法检索的标准元数据。要使用元数据 API 检索调用,请在 Salesforce UI 上将组件添加到您的实践组织。如果您正在处理现有项目,则已经有要检索的组件,可以跳过此步骤。
  3. 步骤 2:生成包 .xml 清单
    package.xml 清单文件列出了要从组织中检索的组件。
  4. 步骤 3:使用元数据 API
    检索组件 使用 Salesforce CLI,检索包.xml 清单中指定组件的文件表示形式。

先决条件

在开始使用元数据 API 进行开发之前,请完成这些先决条件。

  • 要通过命令行访问元数据 API,请安装 Salesforce CLI。
  • 若要创建开发环境,请注册 适用于 Salesforce 开发人员版。Developer Edition 组织是一个免费开发项目 用于独立于生产数据构建和测试解决方案的环境。
  • 安装适用于 Visual Studio Code 的 Salesforce 扩展。 这些工具提供了与开发组织(临时组织、沙箱、 和 DE orgs)、Apex、Aura 组件和 Visualforce。
  • 确认您拥有“已启用 API”权限,并通过元数据 API 修改元数据 “函数”权限或“修改所有数据”权限。如果您没有这些权限 设置、修改元数据权限。
  • 在组织中启用 Dev Hub。Dev Hub 允许你 创建和管理临时组织,以便在不影响生产数据的情况下进行开发 或元数据。
  • 要允许访问受保护的资源(如生产数据和元数据),请授权您的组织。
  • 在组织中启用 Dev Hub。Dev Hub 允许你 创建和管理临时组织,以便在不影响生产数据的情况下进行开发 或元数据。

步骤 1:(可选) 使用 UI 将元数据组件添加到组织

如果您从没有自定义项的新实践组织开始,则只需 具有无法检索的标准元数据。要使用 Metadata API 检索调用,请添加 组件添加到您的实践组织。如果您正在处理现有项目,则 已有要检索的组件,可以跳过此步骤。

  1. 在“设置”中,单击“创建”。
  2. 选择“自定义对象”。
  3. “标签”(Label) 和“复数标签”(Plural Label) 输入任意名称。
  4. 保存组件。

步骤 2:生成包.xml 清单

package.xml 清单文件列出了要从 组织。

Package.xml 清单结构

package.xml 清单使用可扩展标记语言 (XML) 来标识和迁移 元数据组件。package.xml 清单的基本框架是用元素构建的。元素指定元数据类型 你想与之合作。您可以将多个添加到包.xml文件。<types><types><types>

元素内部是元素和元素。元素 选择特定类型的单个组件,<name> 元素选择 元数据组件类型。要使用特定组件,请在元素中输入该组件的 。<types><name><members><members>fullName<members>

例如,若要检索 Account 组件,请在 package.xml 的元素中添加 Account,并在元素中添加 CustomObject。当您发出检索调用时,您将检索 仅来自您组织的 Account 组件。<members><name>

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

检索自定义对象

若要检索元数据类型的所有组件,请不要指定组件的组件。请改用通配符 *(星号)。一些 组件(如标准对象)不支持 *(星号)作为说明符。fullName<members>

要从您的组织中检索所有自定义对象,请执行以下操作:

  1. (可选)如果您没有项目文件夹,请使用 Salesforce CLI 创建一个 用于组织项目的新目录。使用指定的 楼盘名称:sf project generate –name YourProjectName
  2. 在项目中创建名为 package.xml 的文件。
  3. 在文本编辑器中,打开文件并粘贴以下脚本:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

现在您有一个 package.xml 文件,我们可以使用它来检索所有自定义对象。什么时候 您可以自己开发更多组件,您可以使用以下命令从您的组织中检索更多组件 多个元素。<types>

步骤 3:使用元数据 API 检索组件

使用 Salesforce CLI,检索 包 .xml 清单。

元数据 API 检索的两个选项

您可以使用以下两个命令之一来检索元数据组件。

  1. 若要检索 package.xml 清单中指定的组件,请发出 使用 Salesforce CLI 命令检索呼叫。在命令行中,运行此调用 替换为适当的文件路径:sf project retrieve start –manifest path/to/package.xml元数据是异步的, 基于文件的命令。您可以发出多个检索或部署请求,这些请求 当资源可用时,它们会自行运行。retrieve()使用此命令,您可以 发送请求以检索 包 .xml 清单。您的请求将排队等待,直到我们的系统准备就绪 处理您的检索调用。在您的请求被取消排队后,您的检索 调用已运行。客户端检查检索的状态并通知您 通话完成后。调用返回 选择的组件。当您使用 Salesforce CLI 发出检索调用时,所有 这些过程是自动化的。该命令允许源跟踪。源 跟踪包括有关您正在处理的修订版的信息,以及 当进行最后一次更改时,这使得源命令更多 对开发人员友好。要使用源跟踪,请确保在 组织。project retrieve start
  2. 或者,在终端中运行以下命令:sf project retrieve start –manifest path/to/package.xml –target-metadata-dir path/to/retrieve/dir此命令 以 MDAPI 格式(而不是源格式)检索组件,并且不会 允许源跟踪。在实践中,管理员更频繁地使用 mdapi 命令 因为这些命令不包括源跟踪。

为元数据 API 构建客户端应用程序

使用元数据 API 检索、部署、创建、更新或删除 组织的自定义项。最常见的用途是从 沙盒或测试组织添加到您的生产环境。元数据 API 适用于 管理自定义项和构建可以管理元数据模型的工具, 而不是数据本身。

Salesforce CLI 自动执行元数据 API 的基础调用。但是,您可以使用这些 直接使用您自己的客户端应用程序进行调用。本指南为您提供了所有信息 require 开始编写直接使用元数据 API 来管理自定义项的应用程序 为您的组织。它向您展示了如何开始使用基于文件的开发。为 基于 CRUD 的开发示例,请参阅 Java 基于 CRUD 的开发示例 同步调用。

先决条件

在开始使用元数据 API 之前,请确保完成这些先决条件。

  • 创建开发环境。我们强烈建议您使用沙盒,它是 生产组织。企业版、无限制版和性能版随附 免费的开发者沙盒。有关详细信息,请参阅 http://www.salesforce.com/platform/cloud-infrastructure/sandbox.jsp。或者,您可以使用 Developer Edition (DE) 组织。DE 组织提供对 Enterprise Edition 提供的所有功能,但受用户数量限制 以及存储空间的大小。DE 组织不是生产组织的副本/它提供了一个 您可以在其中构建和测试解决方案而不会影响 组织的数据。Developer Edition 帐户可在 https://developer.salesforce.com/signup 免费获得。
  • 标识具有“已启用 API”权限和“修改元数据”的用户 元数据 API 函数权限或修改所有数据权限。这些权限是 需要访问元数据 API 调用。注意如果用户需要访问元数据,但不需要 data,请启用“通过元数据 API 函数修改元数据”权限。否则 启用“修改所有数据”权限。
  • 安装 SOAP 客户机。元数据 API 适用于当前的 SOAP 开发环境, 包括但不限于 Visual Studio® .NET 和 Web 服务连接器 (WSC)。在本文档中,我们提供了基于 WSC 和 JDK 6(Java 平台)的 Java 示例 标准版开发套件 6)。若要运行示例,请先下载最新的 force-wsc JAR 文件及其依赖项来自 mvnrepository.com/artifact/com.force.api/force-wsc/。列出了依赖项 在选择版本时的页面上。注意开发平台在以下方面各不相同 SOAP 实现。某些开发平台的实现差异可以 阻止访问元数据 API 中的部分或全部功能。

步骤 1:生成或获取 Web 服务 组织的 WSDL

若要访问元数据 API 调用,需要 Web 服务描述语言 (WSDL) 文件。The WSDL file 定义可供您使用的 Web 服务。您的开发平台使用 此 WSDL 生成存根代码以访问它定义的 Web 服务。您可以获取 WSDL 文件(如果有) 访问 Salesforce 用户界面中的 WSDL 下载页面,您可以生成它 你自己。有关 WSDL 的更多信息,请参见 http://www.w3.org/TR/wsdl

在访问元数据 API 调用之前, 您必须通过身份验证才能使用调用来使用 Web 服务,该调用在企业中定义 WSDL 和合作伙伴 WSDL。因此,您还必须获得以下一项 这些 WSDL。login()具有“通过元数据 API 函数修改元数据”或“修改所有数据”权限的任何用户 可以下载 WSDL 文件以集成和扩展 Salesforce 平台。

注意

如果用户需要访问元数据,但不需要 data,请启用“通过元数据 API 函数修改元数据”权限。否则 启用“修改所有数据”权限。

步骤 3:演练 Java 示例代码中的示例代码使用企业 WSDL,但合作伙伴 WSDL 工作 同样好。

要为您的组织生成元数据和企业 WSDL 文件,请执行以下操作:

  1. 登录到您的 Salesforce 帐户。 您必须以管理员或具有“修改 所有数据“权限。
  2. 在“设置”中,输入“快速查找”框,然后选择“API”。API
  3. 单击“生成元数据 WSDL”,并将 XML WSDL 文件保存到您的文件中 系统。
  4. 单击“生成企业 WSDL”,并将 XML WSDL 文件保存到您的文件中 系统。

第 2 步:将 WSDL 文件导入到 开发平台

获得 WSDL 文件后,将它们导入到开发中 平台,以便您的开发环境可以生成必要的 用于生成客户端 Web 服务应用程序的对象。这 部分提供了 WSC 的示例说明。有关以下内容的说明 其他开发平台,请参阅平台的产品文档。

注意

导入 WSDL 文件的过程与元数据相同 和企业 WSDL 文件。

Java 环境说明 (WSC)

Java 环境通过 Java 对象访问 API,这些对象 充当服务器端对应物的代理。在使用 API 之前,您必须 首先从组织的 WSDL 文件生成这些对象。

每个 SOAP 客户端都有自己的工具用于此过程。对于 WSC,请使用 实用程序。wsdlc

注意

在运行 之前,必须在系统上安装并引用 WSC JAR 文件 在您的类路径中。您可以下载最新的 force-wsc JAR 文件 及其依赖项(依赖项在页面上列出时 从 mvnrepository.com/artifact/com.force.api/force-wsc/ 中选择一个版本。wsdlc的基本语法是:

wsdlc

java -classpath pathToWsc;pathToWscDependencies com.sforce.ws.tools.wsdlc pathToWsdl/WsdlFilename pathToOutputJar/OutputJarFilename

例如,在 Windows 上:

java –classpath force-wsc-30.0.0.jar;ST4-4.0.7.jar;antlr-runtime-3.5.jar com.sforce.ws.tools.wsdlc metadata.wsdl metadata.jar

在 Mac OS X 和 Unix 上,使用冒号而不是分号 类路径中的项:

java –classpath force-wsc-30.0.0.jar:ST4-4.0.7.jar:antlr-runtime-3.5.jar com.sforce.ws.tools.wsdlc metadata.wsdl metadata.jar

wsdlc生成 JAR 文件 以及用于创建客户端的 Java 源代码和字节码文件 应用。对企业 WSDL 重复此过程以创建 一个企业。JAR 文件。

步骤 3:演练 Java 示例代码

导入 WSDL 文件后,可以构建使用 元数据 API。此示例是编写自己的代码的良好起点。

在运行示例之前,请修改项目和代码,以便:

  1. 包括 WSC JAR、其依赖项以及您从 WSDL。注意尽管 WSC 具有其他依赖项,但仅以下示例 需要 Rhino (js-1.7R2.jar),您可以从 mvnrepository.com/artifact/rhino/js 下载。
  2. 使用您的用户名和密码更新方法中的 USERNAME 和 PASSWORD 变量。如果 您当前的 IP 地址不在组织的受信任 IP 范围内,您将 需要将安全令牌附加到密码中。MetadataLoginUtil.login()
  3. 如果您使用的是沙盒,请务必更改登录 URL。

登录实用程序

Java 用户可用于连接到 企业、合作伙伴和元数据 SOAP API。 创建对象并使用企业 WSDL 登录名登录 方法。然后,它检索并创建一个并连接到元数据 API 端点。 定义于 WSC。ConnectorConfigMetadataLoginUtilConnectorConfigsessionIdmetadataServerUrlConnectorConfigConnectorConfig

该类抽象化登录名 示例其他部分的代码,允许重用此代码的某些部分 无需更改不同的 Salesforce API。MetadataLoginUtil

import com.sforce.soap.enterprise.EnterpriseConnection;
import com.sforce.soap.enterprise.LoginResult;
import com.sforce.soap.metadata.MetadataConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;

/**
 * Login utility.
 */
public class MetadataLoginUtil {

    public static MetadataConnection login() throws ConnectionException {
        final String USERNAME = "user@company.com";
        // This is only a sample. Hard coding passwords in source files is a bad practice.
        final String PASSWORD = "password"; 
        final String URL = "https://login.salesforce.com/services/Soap/c/59.0";
        final LoginResult loginResult = loginToSalesforce(USERNAME, PASSWORD, URL);
        return createMetadataConnection(loginResult);
    }

    private static MetadataConnection createMetadataConnection(
            final LoginResult loginResult) throws ConnectionException {
        final ConnectorConfig config = new ConnectorConfig();
        config.setServiceEndpoint(loginResult.getMetadataServerUrl());
        config.setSessionId(loginResult.getSessionId());
        return new MetadataConnection(config);
    }

    private static LoginResult loginToSalesforce(
            final String username,
            final String password,
            final String loginUrl) throws ConnectionException {
        final ConnectorConfig config = new ConnectorConfig();
        config.setAuthEndpoint(loginUrl);
        config.setServiceEndpoint(loginUrl);
        config.setManualLogin(true);
        return (new EnterpriseConnection(config)).login(username, password);
    }
}

注意

此示例使用用户和密码身份验证来获取会话 ID,该 ID 然后用于调用元数据 API。或者,您可以使用 OAuth 认证。使用 OAuth 向 Salesforce 发送请求后,将返回的 访问令牌,而不是会话 ID。例如,将访问令牌传递给 上的调用。了解如何使用 OAuth 在 Salesforce 中进行身份验证,请参阅使用以下方式对应用程序进行身份验证 Salesforce 帮助中的 OAuth。setSessionId()ConnectorConfig

基于文件的 Java 示例代码 发展

示例代码使用登录实用程序登录。然后它显示一个菜单 检索、部署和退出。

和调用都对名为 components.zip 的 .zip 文件进行操作。该调用将组织中的组件检索到 components.zip 中,并且该调用将 components.zip 中的组件部署到组织。如果保存示例 到您的计算机并执行它,首先运行 retrieve 选项,以便您有一个可以随后部署的组件.zip文件。后 检索调用,示例在循环中调用,直到操作完成。 同样,在部署调用之后,示例会在循环中进行检查,直到操作完成。retrieve()deploy()retrieve()deploy()checkRetrieveStatus()checkDeployStatus()

该调用使用清单文件执行以下操作: 确定要从组织中检索的组件。下面是一个示例包 .xml 清单文件。有关 清单文件结构,请参阅使用 Zip 文件部署和检索元数据。在此示例中,清单文件检索所有自定义对象。 自定义选项卡和页面布局。retrieve()

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>*</members>
        <name>Layout</name>
    </types>
    <version>59.0</version>
</Package>

请注意每个 API 调用后面的错误处理代码。

注意

此示例需要 API 版本 34.0 或 后。

import java.io.*;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.rmi.RemoteException;
import java.util.*;

import javax.xml.parsers.*;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import com.sforce.soap.metadata.*;

/**
 * Sample that logs in and shows a menu of retrieve and deploy metadata options.
 */
public class FileBasedDeployAndRetrieve {

    private MetadataConnection metadataConnection;

    private static final String ZIP_FILE = "components.zip";

    // manifest file that controls which components get retrieved
    private static final String MANIFEST_FILE = "package.xml";

    private static final double API_VERSION = 29.0;

    // one second in milliseconds
    private static final long ONE_SECOND = 1000;

    // maximum number of attempts to deploy the zip file
    private static final int MAX_NUM_POLL_REQUESTS = 50;

    private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws Exception {
        FileBasedDeployAndRetrieve sample = new FileBasedDeployAndRetrieve();
        sample.run();
    }

    public FileBasedDeployAndRetrieve() {
    }

    private void run() throws Exception {
        this.metadataConnection = MetadataLoginUtil.login();

        // Show the options to retrieve or deploy until user exits
        String choice = getUsersChoice();
        while (choice != null && !choice.equals("99")) {
            if (choice.equals("1")) {
                retrieveZip();
            } else if (choice.equals("2")) {
                deployZip();
            } else {
                break;
            }
            // show the options again
            choice = getUsersChoice();
        }
    }

    /*
     * Utility method to present options to retrieve or deploy.
     */
    private String getUsersChoice() throws IOException {
        System.out.println(" 1: Retrieve");
        System.out.println(" 2: Deploy");
        System.out.println("99: Exit");
        System.out.println();
        System.out.print("Enter 1 to retrieve, 2 to deploy, or 99 to exit: ");
        // wait for the user input.
        String choice = reader.readLine();
        return choice != null ? choice.trim() : "";
    }

    private void deployZip() throws Exception {
        byte zipBytes[] = readZipFile();
        DeployOptions deployOptions = new DeployOptions();
        deployOptions.setPerformRetrieve(false);
        deployOptions.setRollbackOnError(true);
        AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
        DeployResult result = waitForDeployCompletion(asyncResult.getId());
        if (!result.isSuccess()) {
            printErrors(result, "Final list of failures:\n");
            throw new Exception("The files were not successfully deployed");
        }
        System.out.println("The file " + ZIP_FILE + " was successfully deployed\n");
    }

    /*
    * Read the zip file contents into a byte array.
    */
    private byte[] readZipFile() throws Exception {
        byte[] result = null;
        // We assume here that you have a deploy.zip file.
        // See the retrieve sample for how to retrieve a zip file.
        File zipFile = new File(ZIP_FILE);
        if (!zipFile.exists() || !zipFile.isFile()) {
            throw new Exception("Cannot find the zip file for deploy() on path:"
                + zipFile.getAbsolutePath());
        }

        FileInputStream fileInputStream = new FileInputStream(zipFile);
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while (-1 != (bytesRead = fileInputStream.read(buffer))) {
                bos.write(buffer, 0, bytesRead);
            }

            result = bos.toByteArray();
        } finally {
            fileInputStream.close();
        }
        return result;
    }

    /*
    * Print out any errors, if any, related to the deploy.
    * @param result - DeployResult
    */
    private void printErrors(DeployResult result, String messageHeader) {
        DeployDetails details = result.getDetails();
        StringBuilder stringBuilder = new StringBuilder();
        if (details != null) {
            DeployMessage[] componentFailures = details.getComponentFailures();
            for (DeployMessage failure : componentFailures) {
                String loc = "(" + failure.getLineNumber() + ", " + failure.getColumnNumber();
                if (loc.length() == 0 && !failure.getFileName().equals(failure.getFullName()))
                {
                    loc = "(" + failure.getFullName() + ")";
                }
                stringBuilder.append(failure.getFileName() + loc + ":" 
                    + failure.getProblem()).append('\n');
            }
            RunTestsResult rtr = details.getRunTestResult();
            if (rtr.getFailures() != null) {
                for (RunTestFailure failure : rtr.getFailures()) {
                    String n = (failure.getNamespace() == null ? "" :
                        (failure.getNamespace() + ".")) + failure.getName();
                    stringBuilder.append("Test failure, method: " + n + "." +
                            failure.getMethodName() + " -- " + failure.getMessage() + 
                            " stack " + failure.getStackTrace() + "\n\n");
                }
            }
            if (rtr.getCodeCoverageWarnings() != null) {
                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
                    stringBuilder.append("Code coverage issue");
                    if (ccw.getName() != null) {
                        String n = (ccw.getNamespace() == null ? "" :
                        (ccw.getNamespace() + ".")) + ccw.getName();
                        stringBuilder.append(", class: " + n);
                    }
                    stringBuilder.append(" -- " + ccw.getMessage() + "\n");
                }
            }
        }
        if (stringBuilder.length() > 0) {
            stringBuilder.insert(0, messageHeader);
            System.out.println(stringBuilder.toString());
        }
    }
    

    private void retrieveZip() throws Exception {
        RetrieveRequest retrieveRequest = new RetrieveRequest();
        // The version in package.xml overrides the version in RetrieveRequest
        retrieveRequest.setApiVersion(API_VERSION);
        setUnpackaged(retrieveRequest);

        AsyncResult asyncResult = metadataConnection.retrieve(retrieveRequest);
        RetrieveResult result = waitForRetrieveCompletion(asyncResult);

        if (result.getStatus() == RetrieveStatus.Failed) {
            throw new Exception(result.getErrorStatusCode() + " msg: " +
                    result.getErrorMessage());
        } else if (result.getStatus() == RetrieveStatus.Succeeded) {  
	        // Print out any warning messages
	        StringBuilder stringBuilder = new StringBuilder();
	        if (result.getMessages() != null) {
	            for (RetrieveMessage rm : result.getMessages()) {
	                stringBuilder.append(rm.getFileName() + " - " + rm.getProblem() + "\n");
	            }
	        }
	        if (stringBuilder.length() > 0) {
	            System.out.println("Retrieve warnings:\n" + stringBuilder);
	        }
	
	        System.out.println("Writing results to zip file");
	        File resultsFile = new File(ZIP_FILE);
	        FileOutputStream os = new FileOutputStream(resultsFile);
	
	        try {
	            os.write(result.getZipFile());
	        } finally {
	            os.close();
	        }
        }
    }

    private DeployResult waitForDeployCompletion(String asyncResultId) throws Exception {
        int poll = 0;
        long waitTimeMilliSecs = ONE_SECOND;
        DeployResult deployResult;
        boolean fetchDetails;
        do {
            Thread.sleep(waitTimeMilliSecs);
            // double the wait time for the next iteration

            waitTimeMilliSecs *= 2;
            if (poll++ > MAX_NUM_POLL_REQUESTS) {
                throw new Exception(
                    "Request timed out. If this is a large set of metadata components, " +
                    "ensure that MAX_NUM_POLL_REQUESTS is sufficient.");
            }
            // Fetch in-progress details once for every 3 polls
            fetchDetails = (poll % 3 == 0);

            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
            System.out.println("Status is: " + deployResult.getStatus());
            if (!deployResult.isDone() && fetchDetails) {
                printErrors(deployResult, "Failures for deployment in progress:\n");
            }
        }
        while (!deployResult.isDone());

        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
                    deployResult.getErrorMessage());
        }
        
        if (!fetchDetails) {
            // Get the final result with details if we didn't do it in the last attempt.
            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
        }
        
        return deployResult;
    }

    private RetrieveResult waitForRetrieveCompletion(AsyncResult asyncResult) throws Exception {
    	// Wait for the retrieve to complete
        int poll = 0;
        long waitTimeMilliSecs = ONE_SECOND;
        String asyncResultId = asyncResult.getId();
        RetrieveResult result = null;
        do {
            Thread.sleep(waitTimeMilliSecs);
            // Double the wait time for the next iteration
            waitTimeMilliSecs *= 2;
            if (poll++ > MAX_NUM_POLL_REQUESTS) {
                throw new Exception("Request timed out.  If this is a large set " +
                "of metadata components, check that the time allowed " +
                "by MAX_NUM_POLL_REQUESTS is sufficient.");
            }
            result = metadataConnection.checkRetrieveStatus(
                    asyncResultId, true);
            System.out.println("Retrieve Status: " + result.getStatus());
        } while (!result.isDone());         

        return result;
    }

    private void setUnpackaged(RetrieveRequest request) throws Exception {
        // Edit the path, if necessary, if your package.xml file is located elsewhere
        File unpackedManifest = new File(MANIFEST_FILE);
        System.out.println("Manifest file: " + unpackedManifest.getAbsolutePath());

        if (!unpackedManifest.exists() || !unpackedManifest.isFile()) {
            throw new Exception("Should provide a valid retrieve manifest " +
                "for unpackaged content. Looking for " +
                unpackedManifest.getAbsolutePath());
        }

        // Note that we use the fully quualified class name because
        // of a collision with the java.lang.Package class
        com.sforce.soap.metadata.Package p = parsePackageManifest(unpackedManifest);
        request.setUnpackaged(p);
    }

    private com.sforce.soap.metadata.Package parsePackageManifest(File file)
            throws ParserConfigurationException, IOException, SAXException {
        com.sforce.soap.metadata.Package packageManifest = null;
        List<PackageTypeMembers> listPackageTypes = new ArrayList<PackageTypeMembers>();
        DocumentBuilder db =
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
        InputStream inputStream = new FileInputStream(file);
        Element d = db.parse(inputStream).getDocumentElement();
        for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling()) {
            if (c instanceof Element) {
                Element ce = (Element) c;
                NodeList nodeList = ce.getElementsByTagName("name");
                if (nodeList.getLength() == 0) {
                    continue;
                }
                String name = nodeList.item(0).getTextContent();
                NodeList m = ce.getElementsByTagName("members");
                List<String> members = new ArrayList<String>();
                for (int i = 0; i < m.getLength(); i++) {
                    Node mm = m.item(i);
                    members.add(mm.getTextContent());
                }
                PackageTypeMembers packageTypes = new PackageTypeMembers();
                packageTypes.setName(name);
                packageTypes.setMembers(members.toArray(new String[members.size()]));
                listPackageTypes.add(packageTypes);
            }
        }
        packageManifest = new com.sforce.soap.metadata.Package();
        PackageTypeMembers[] packageTypesArray =
                new PackageTypeMembers[listPackageTypes.size()];
        packageManifest.setTypes(listPackageTypes.toArray(packageTypesArray));
        packageManifest.setVersion(API_VERSION + "");
        return packageManifest;
    }
}

元数据 API 开发人员指南

Salesforce 元数据

元数据是描述其他数据的数据。要了解 Salesforce 如何定义元数据, 将业务数据与 Salesforce 元数据进行对比。业务数据包括以下记录: 直接对应于您公司的业务,例如地址、帐户或产品。 Salesforce 元数据描述了架构、流程、表示、授权和常规 Salesforce 组织的配置。

要将 Salesforce 元数据与业务数据进行对比,请首先检查架构元数据的 描述业务数据的属性。例如,Salesforce 标准对象 Address 具有架构元数据和业务数据。 地址字段(如 、 和 )都是架构元数据。每个中的相应值 字段,例如邮寄地址、伊利诺伊州芝加哥和 60106,都是数据。 而个人 身份信息 (PII) 通常存在于业务数据中,元数据还可以包括 PII,例如自定义对象名称、报告名称等。Address TypeCityPostal Code

Salesforce 中的元数据还定义了组织的运作方式。例如,流程元数据 描述当用户按下“保存”按钮时发生的情况。演示文稿元数据问题 组织的布局和授权元数据决定了用户访问权限。Salesforce的 元数据还描述了组织的常规配置。例如,您可以配置 Chatter 阻止帖子中的表情符号。

元数据 API 适用于元数据类型和组件。元数据类型定义 应用程序元数据的结构。元数据组件是元数据类型的实例。 元数据类型的字段和值都是元数据。例如,元数据类型 CustomTab 表示显示内容的自定义选项卡。这 CustomTab 字段指示选项卡是否位于侧边栏面板上, 这是元数据确定表示的一个示例。元数据类型,如 CustomTab 构建元数据模型,描述组织的结构、显示或功能。 使用元数据 API 开发自定义项并构建用于管理元数据模型的工具, 而不是数据本身。hasSidebar

元数据 API 功能

元数据 API 的主要目的是在 Salesforce 组织在开发过程中。使用元数据 API 进行部署、检索、 创建、更新或删除自定义信息,例如自定义对象定义和 页面布局。元数据 API 不直接处理业务数据。要创建, 检索、更新或删除记录,例如客户或潜在客户,使用 SOAP API 或 REST API。

您可以使用以下两种方式之一移动元数据。第一种方法是使用元数据 API 和调用。管理员通常使用 and 调用来移动完整的元数据模型。这些调用 最适合开发的最后阶段,例如将经过测试的自定义项部署到 生产组织。deploy()retrieve()deploy()retrieve()

第二种方法是源推送和拉取命令,这些命令仅移动元数据中的更改。 这些命令使用源跟踪,这使得它们对开发人员更友好,也更好 用于中间开发阶段。

元数据 API 的用例

在开发过程中,使用元数据 API 在组织之间移动元数据 周期。元数据 API 还用于从 发展。

要了解如何使用元数据 API,假设您是 Zephyrus 的 Salesforce 开发人员 搬迁服务。Zephyrus 是一家人才流动公司,帮助公司开发流程 用于国内和国际员工搬迁。Zephyrus 正在向亚洲和南部扩张 美国,并希望为这两个地区增加定向服务。迎新服务包括 在住房和学校搜索、地区旅游和交通方面提供国内援助 信息。

您的开发团队必须将这些新的定向服务添加到其现有组织中。产品 例如,国内方向是可以在 Salesforce 中自定义的对象。当您添加 对象并自定义您的组织,您可以更改其元数据。创建 自定义产品是元数据 API 可以提供帮助的地方。

在开发过程中使用元数据 API

目前,Zephyrus 拥有为其他 国家。若要开始构建新产品自定义项,需要现有的 Zephyrus 生产 Salesforce 组织中的配置位于单独的存储库中。这 生产组织的配置都是元数据。要将生产元数据保存在 存储库,将元数据从 Zephyrus 生产组织移动到本地文件系统。

将元数据从生产环境移动到本地文件系统

在不进行开发更改的情况下进行开发更改 影响现有配置,请使用元数据 API 将元数据移动到本地文件 系统。接下来,将元数据从本地文件系统推送到可共享的存储库,以便 发展。

检索到所有 Zephyrus 元数据后,您可以在本地或临时组织中进行开发。抓 组织是没有数据的一次性 Salesforce 环境。许多开发人员同时使用这两种工具 一起。在本地加载文件和进行更改比在临时执行要快得多 组织。开发人员通常在其本地文件系统上构建自定义项,并在临时运行测试 组织。在测试和开发时,在本地文件系统和临时组织之间移动更改。

将元数据更改移入和移出临时组织

您可以使用临时组织 使用本地文件系统来开发和测试对元数据的更改。要移动更改,请执行以下操作 在本地与 scratch 组织进行本地创建,使用元数据 API。

Zephyrus 开发团队的其他成员都有自己的自定义项。在开发和 您可以自行测试,现在是团队集成更改并在沙盒中运行测试的时候了。 沙盒是用于开发和测试集成的开发环境。

将元数据移动到集成点的沙盒

在开发过程中,使用元数据 用于将元数据移动到沙盒的 API,用于集成更改、测试和协作 团队。

在团队构建定向服务自定义并完成测试后,部署 这些组件使用元数据 API 进行生产。

将元数据部署到生产环境

在最后一步 开发周期,将自定义项从源代码管理系统(如 Git)移动到生产环境 使用元数据 API。

其他用例

您可以使用元数据 API 在 Salesforce 中进行较大的更改,例如拆分和合并 生产组织。

例如,Zephyrus 希望将公司拆分为两个部门,一个部门专门从事 国内搬迁和另一个国际搬迁。在这种情况下,您拆分了 Zephyrus 的 Salesforce 组织并决定哪些元数据属于哪个组织。元数据 API 可以将元数据移动到 新组织。

然后,假设 Zephyrus 收购了 Apollo Global Relocation,两家公司都使用 Salesforce。 要整合信息,您可以使用元数据 API 将 Apollo 组织合并到 Zephyrus 中 组织。

移动生产级更改的元数据

使用元数据 API 移动元数据 在大型更改期间,例如合并或拆分 Salesforce 组织。

您可以使用元数据 API 在开发过程中进行配置更改,这些更改是 对于其他 API 调用来说太大。例如,Zephyrus 支持多种语言,因为它们 全球客户。要为对象翻译不同的语言,请包含一个对象 每种语言的翻译文件。

进行大型元数据配置更改

元数据更适合 用于向组织部署大型更改的其他 API。

将元数据从生产环境移动到本地文件系统

在不影响现有 配置,请使用元数据 API 将元数据移动到本地文件系统。接下来,推送 元数据从本地文件系统传输到可共享的存储库,用于 发展。

在 Salesforce 上构建自定义项时,必须保留 开发周期中的现有组织。若要在不影响自定义项的情况下构建自定义项,请执行以下操作 生产组织,将生产元数据保存在版本控制系统中。Git 集成最好 使用 SFDX 工具。

首先,将所需的元数据从生产组织移动到本地文件系统。移动 元数据到本地计算机,请使用检索调用而不是源拉取。接下来,推动你的 文件复制到团队成员可通过 Git 命令访问的存储库中。这 存储库现在是团队开发的生产元数据的原始来源 周期。

现在,您的生产元数据已存储在存储库中,请将必要的元数据移回 到本地文件系统以开始开发工作。

将元数据更改移入和移出临时组织

使用临时组织来开发和测试对元数据的更改。您可以 使用 Salesforce CLI 或 Salesforce 在临时组织内部或外部执行开发 VS Code 的扩展,利用元数据 API 的强大功能。

临时组织是空的,以便开发人员可以指定确切的元数据和数据 从源代码管理系统中包含。临时组织的生命周期在 创建,1-30 天。它们是短暂的,以确保真相的来源始终是来源 控制系统,而不是组织本身。

您可以使用 Salesforce 将元数据从源代码管理系统或临时组织移动到临时组织 由于临时组织使用源跟踪来识别更改,因此 CLI 是最 在本地存储库和临时组织之间移动元数据的有效方法。继续 遍历在本地文件系统和 暂存组织,直到开发完成。

将元数据移动到集成点的沙盒

在开发过程中,使用元数据 API 将元数据移动到沙盒 集成更改、测试并与您的团队协作。

在临时组织或本地文件系统中自行开发后,将 团队在沙盒中的集成点。沙盒是您可以使用的开发环境 集成和测试来自多个开发人员的更改。管理员通常会创建和分配沙盒。 要在 Salesforce UI 上创建沙盒,请导航到设置。接下来,在“快速查找”框中,搜索 用于沙盒。

您有多个级别的沙盒可供选择,其中包含不同的数据量。这 Developer Sandbox 和 Developer Pro Sandbox 是用于构建的开发环境 对虚构数据进行自定义和测试更改。“部分复制”沙箱和“完整”沙箱是 加载了生产数据副本的测试环境。将元数据移动到不同的沙盒 使用元数据 API 部署命令,具体取决于您的开发和测试需求。

在元数据 API 之外,管理员通常使用更改集从一个 沙盒到另一个。与元数据 API 调用不同,您必须手动构建更改集。要添加 组件到持续集成系统中更容易,您可以自动执行元数据 API 调用 Salesforce 命令行界面。

将元数据部署到生产环境

在开发周期的最后一步中,将自定义项从 源代码控制系统(如 Git)使用元数据 API 投入生产。

当您的团队完成集成测试并准备好部署到生产环境时,请将 完成从本地环境到存储库的自定义。对于版本,请移动 通过将更新的存储库拉回本地,将元数据从存储库拉回生产环境 环境。接下来,使用元数据 API deploy 将元数据部署到生产环境 叫。

将元数据移动到生产环境需要部署调用而不是推送命令,因为 deploy 调用部署整个元数据模型,而不仅仅是元数据中的更改。

部署最近的验证

常规部署调用会执行可能需要很长时间才能完成的自动化 Apex 测试。自 跳过已验证组件的测试并快速将组件部署到生产环境,使用 Deploy 最近的验证选项。

移动生产级更改的元数据

使用元数据 API 在大型更改期间移动元数据,例如 合并或拆分 Salesforce 组织。

要拆分组织,请先检索要移动的元数据。然后,使用 deploy 调用 将这些配置推送到新组织。同样,要合并两个组织,请检索 来自一个组织的现有元数据。接下来,使用 deploy 调用将元数据从 一个组织到另一个组织。

进行大型元数据配置更改

元数据 API 比其他 API 更适合部署大型 对 Salesforce 组织的更改。

元数据 API 和调用是基于文件的,因此 异步。使用同步命令时,大型配置更改需要 加载时间过长。相反,部署和检索调用会以异步方式开始 完成时通知您的流程。由于基于文件的调用是异步的, 元数据 API 还可以处理部署请求队列。deploy()retrieve()

元数据 API 发行说明

使用 Salesforce 发行说明了解 元数据 API。

有关影响 Salesforce Platform 的更新和更改,包括元数据 API,请参阅 API 发行说明。

有关新的、已更改的和已弃用的元数据类型以及特定于元数据 API 的其他更改,请参阅 Salesforce 发行说明中的元数据 API。

元数据 API 开发人员工具

在 Salesforce CLI 上使用适用于 Visual Studio Code 的 Salesforce 扩展访问元数据 API 命令。Salesforce CLI 和 Salesforce Extensions for Visual Studio Code 简化了 使用元数据 API 的过程。访问元数据中功能的最简单方法 API 是使用 Salesforce Extensions for Visual Studio Code 或 Salesforce 这两个工具都建立在元数据 API 之上,并使用标准工具来 简化元数据 API 的使用。

  • 适用于 Visual Studio Code 的 Salesforce 扩展包括以下工具: 在 Salesforce 平台上使用轻量级、可扩展的 VS Code 进行开发 编辑 器。这些工具提供了与开发组织合作的功能 (临时组织、沙盒和 DE 组织)、Apex、Aura 组件和 视觉力。
  • 如果您使用脚本或命令行,Salesforce CLI 是理想的选择 在本地目录和 Salesforce 之间移动元数据 组织。

有关 Salesforce Extensions for Visual 的更多信息 Studio Code 或 Salesforce CLI,请参阅 Salesforce 工具和工具包。

如果您更喜欢构建自己的客户端应用程序,则 Metadata API 的基础调用 已公开供您直接使用。本指南为您提供有关工作的更多信息 直接使用元数据 API。

您可以使用元数据 API 来管理设置和自定义信息(元数据) Salesforce的。例如:

  • 将自定义项导出为 XML 元数据文件。请参阅使用 Zip 文件和 retrieve()。
  • 在组织之间迁移配置更改。参见 deploy() 和 retrieve()。
  • 使用 XML 元数据文件修改现有自定义项。参见 deploy() 和 retrieve()。
  • 以编程方式管理自定义项。请参阅基于 CRUD 的元数据开发。

您可以在 Developer Edition 或沙箱中修改测试组织中的元数据,然后进行部署 测试了对 Enterprise、Unlimited 或 Performance Edition 中生产组织的更改。您可以 此外,还可以创建脚本,以使用自定义对象、自定义字段和其他对象填充新组织 组件。

支持的 Salesforce 版本

若要使用元数据 API,您的组织必须使用 Enterprise Edition, Unlimited Edition、Performance Edition 或 Developer Edition。如果您是现有 想要升级到 Enterprise、Unlimited 或 Performance Edition 的 Salesforce 客户, 请联系您的客户代表。

我们强烈建议您使用沙盒,它是 生产组织。企业版、无限制版和性能版随附 免费的开发者沙盒。有关详细信息,请参阅 http://www.salesforce.com/platform/cloud-infrastructure/sandbox.jsp。

或者,您可以使用 Developer Edition (DE) 组织。DE 组织提供对 Enterprise Edition 提供的所有功能,但受用户数量限制 以及存储空间的大小。DE 组织不是生产组织的副本/它提供了一个 您可以在其中构建和测试解决方案而不会影响 组织的数据。Developer Edition 帐户可在 https://developer.salesforce.com/signup 免费获得。

注意

元数据组件必须在组织中可见,元数据 API 才能对其执行操作。此外,一个 用户必须具有 API Enabled 权限才能访问元数据组件。

专业版元数据 API 访问

ISV 合作伙伴可以请求对 Professional Edition 组织的元数据 API 访问权限,这些应用程序具有以下特点 已通过 AppExchange 安全审核。访问权限是通过 API 令牌(客户端 ID)授予的。 此特殊密钥使应用程序能够向客户的 Professional 进行元数据 API 调用 版本组织。

作为 ISV 合作伙伴,可以按照以下步骤请求元数据 API 访问权限。

  1. 提交您的应用进行安全审核。请参阅安全性中的步骤 在 ISVForce 中查看 指南。
  2. 在您的应用程序获得批准后,在合作伙伴社区中的 AppExchange 和功能请求 |API 令牌请求,并为令牌类型指定 SOAP。

若要调用元数据 API,请在调用中将 API 令牌追加到 CallOptions SOAP 标头。

元数据 API 编辑访问权限

要使用元数据 API,用户必须具备以下条件。

  • 以下版本之一:企业版、无限制版或开发人员版
  • “通过元数据 API 函数修改元数据”或“修改所有数据”权限
  • 允许使用他们想要的元数据所支持的功能的权限 修改
  • 启用其部署工具(例如 Salesforce CLI、更改集或 蚂蚁迁移工具

通过元数据 API 函数修改元数据权限,用户可以访问和编辑 元数据通过元数据 API,只要用户具有访问所需的任何其他权限 某些元数据类型。此附加权限信息列在元数据中 每种元数据类型的 API 开发人员指南。具有“修改所有数据”权限的用户 可以访问和编辑所有数据。

“通过元数据 API 函数修改元数据”权限不影响直接 使用设置 UI 页面自定义元数据,因为这些页面不使用元数据 API 更新。

某些元数据(如 Apex)在系统上下文中执行,因此请注意如何委派 通过元数据 API 函数权限修改元数据。通过元数据修改元数据 API 函数权限允许部署 Apex 元数据,但不允许某些 Apex 仍需要“修改所有数据”权限的开发和调试功能。

在以下情况下,将自动启用“通过元数据 API 函数修改元数据”权限 选择“部署更改集”或“创作 Apex”权限。

当“管理提示”用户权限和“通过元数据修改元数据”API 函数时 权限组合在一起,用户可以在 Lightning Experience 中管理应用程序内指导。

开发平台

元数据 API 支持基于文件和基于 CRUD 的开发。

基于文件的开发

声明性或基于文件的异步元数据 API deploy() 和 retrieve() 操作 部署或检索包含组件的文件 一组文件夹和一个名为 package.xml 的清单文件。查看更多 信息,请参阅部署和检索 元数据。访问基于文件的功能的最简单方法是使用 适用于 Visual Studio Code 的 Salesforce 扩展或 Ant 迁移工具。.zip

基于 CRUD 的开发

CRUD 元数据 API 调用作用于元数据组件 其方式类似于企业 WSDL 中同步 API 调用的行为方式 在对象上。有关企业 WSDL 的更多信息,请参见《SOAP API 开发人员指南》。

标准符合性

元数据 API 的实现符合以下规范:

标准名称网站
简单对象访问协议 (SOAP) 1.1http://www.w3.org/TR/2000/NOTE-SOAP-20000508/
Web 服务描述语言 (WSDL) 1.1http://www.w3.org/TR/2001/NOTE-wsdl-20010315
WS-I 基本概要文件 1.1http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html

元数据 API 支持策略

Salesforce 支持以前版本的元数据 API。但是,您的新客户端应用程序 应使用最新版本的 Lightning 平台元数据 API WSDL 文件,以完全 利用更丰富的功能和更高的效率。

向后兼容性

Salesforce 努力使使用 Lightning 平台时的向后兼容性变得容易。

每个新的 Salesforce 版本都由两个组件组成:

  • 驻留在 Salesforce 系统上的平台软件的新版本
  • API 的新版本

例如,Spring ’07 版本包括 API 版本 9.0 和 Summer ’07 版本 包括 API 版本 10.0。

我们维护对平台软件各个版本的每个 API 版本的支持。该 API 是 向后兼容,因为为使用给定 API 版本而创建的应用程序将 在将来的平台软件版本中继续使用相同的 API 版本。

Salesforce 不保证针对一个 API 版本编写的应用程序能够正常工作 对于未来的 API 版本:方法签名和数据表示形式的更改通常是 当我们继续增强 API 时,需要。但是,我们努力使 API 保持一致,以免 版本到版本,将应用程序移植到较新的 API 所需的更改(如果有)最少 版本。

例如,使用 Spring 附带的 API 版本 9.0 编写的应用程序 ’07 版本,将继续在 Summer ’07 版本上使用 API 版本 9.0, 以及以后的版本。但是,同一应用程序可能无法与 API 一起使用 版本 10.0,无需对应用程序进行修改。

API 生命周期终止政策

查看支持、不支持的元数据 REST 和 SOAP API 版本,或者 不能利用的。

Salesforce 承诺支持每个 API 版本至少 3 个 自首次发布之日起的年。为了提高质量和性能 API,有时不再支持超过 3 年的版本。

Salesforce 通知使用计划的 API 版本的客户 为 折旧 至少 1 年后,对版本的支持将结束。

Salesforce API 版本版本支持状态版本停用信息
版本 31.0 至 59.0支持。
版本 21.0 至 30.0截至 22 年夏季,这些版本已被弃用,并且没有 Salesforce 支持的时间更长。从 25 年夏季开始,这些 版本将停用且不可用。Salesforce Platform API 版本 21.0 到 30.0 停用
版本 7.0 至 20.0自 22 年夏季起,这些版本已停用,并且 不能利用的。Salesforce Platform API 版本 7.0 到 20.0 停用

如果你 请求任何资源或使用已停用的 API 版本 REST API 中的操作 返回错误代码。410:GONE

如果您要求任何 资源或使用已停用的 API 版本中的操作,SOAP API 将返回错误代码。500:UNSUPPORTED_API_VERSION

识别 从旧的或不受支持的 API 版本发出的请求,请使用 API 总使用量事件类型。

相关资源

Salesforce 开发人员网站提供一整套开发人员工具包、示例代码、示例 SOAP 消息、基于社区的支持和其他资源可帮助您进行开发 项目。请务必访问 https://developer.salesforce.com/page/Getting_Started 了解更多信息 信息,或访问 https://developer.salesforce.com/signup 注册一个免费的 Developer Edition 帐户。

您可以访问以下网站以了解有关 Salesforce 应用程序的更多信息:

  • Salesforce 开发人员提供有用的信息 开发 人员。
  • Salesforce 用于 有关 Salesforce 应用程序的信息。
  • 闪电平台 AppExchange,用于访问为 Salesforce 创建的应用程序。
  • 开拓者 社区提供服务,以确保 Salesforce 客户取得成功。