abivia / nextform
Abivia Next 表单生成器
Requires
- php: >=7.4
- abivia/configurable: ^1.0
- doctrine/dbal: ^2.0
- illuminate/translation: ^6.0|^7.0|^8.0
- myclabs/deep-copy: ^1.9
- symfony/yaml: ^5.1@dev
Requires (Dev)
- nunomaduro/phpinsights: ^1.14.0
- phpunit/phpunit: ^9.0-stable
README
最新更新
- 添加 Laravel 风格的验证规则。实现了 Data\Presentation、Data\Store 类和 Data\Property 的角色属性的紧凑 JSON 表单。
- 在段中自动设置标签简化了基于消息 ID 的翻译。
- 扩展和简化了基于角色的字段可见性。
- 修复了半通不通的 README.md
关于 NextForm
NextForm 是一个基于 PHP 的表单生成器,具有可选的 Laravel 集成(请参阅 NextForm-Laravel)。NextForm 主要为需要运行时修改表单定义的应用程序而设计。表单可以即时定义,也可以由 JSON 或 YAML 文件定义。没有表单布局 GUI。
NextForm 还可以将其数据结构写入 JSON。您可以在即时构建表单并保存供以后使用。
表单定义在渲染引擎之间是相同的。目前提供简单 HTML 和 Bootstrap 4 引擎,更多引擎计划中。
表单由两个数据结构定义。`Schema` 结构详细说明了可以出现在表单上的数据。`Form` 结构指定了这些数据元素的顺序和布局。在 simplest 情况下,表单定义的精髓是 schema 中定义的元素列表。
"elements": ["firstName", "lastName", "email"]
如果您的设计团队决定他们想将电子邮件地址放在第一位,只需重新排列元素即可。
"elements": ["email", "firstName", "lastName"]
如果他们希望姓名和姓氏在同一行
"elements": [
"email",
{
"type": "cell",
"elements": ["firstName", "lastName"]
}
]
NextForm 设计用来消除其他常见问题
- 没有模板。无需混合 HTML 和 PHP 或 HTML 和模板语言。使用
NextForm::body();在一行中注入您的表单到页面中。 - 没有 CSS。使用基本设置获取看起来不错的表单,让 NextForm 处理 CSS。在 Bootstrap 中,通过一个设置(layout:vertical 或 layout:horizontal)在垂直和水平表单布局之间切换。
- 不同角色的不同表单。如果您有不同访问角色的不同用户组,很可能会拥有多个定义非常相似但针对每个角色都不同的表单。NextForm 的基于角色的字段权限让您可以将所有这些变体合并到一个易于维护的版本中。
- 由于表单通常仅在一个应用程序的视图中定义,它们通常是不可变的,难以转换。NextForm 提供了在生成之前对表单进行程序性转换的功能(例如,添加字段,在单选组中添加/删除选项等)。这为 MVC 应用程序提供了通常仅通过客户端框架(如 Vue)实现的特性。
- 框架可以很好地完成呈现和验证,但通常不提供对表单元素之间客户端交互的支持。
太多的表单脆弱、重复、难以维护,阻碍了快速开发。NextForm 提供了良好的可重用性、简洁的表单规范、细粒度访问控制以及跨客户端框架的可移植性。
安装
使用 composer 安装:composer require abivia/nextform
此包中的测试包含多个使用示例。
对于 Laravel 集成,需要 abivia/nextform-laravel。可以在 NextForm Laravel Demo 找到 NextForm 在 Laravel 中的使用示例。
示例
在没有教程的情况下,最好的例子可以在 tests/integrated/ 集成测试文件夹中找到。 AccessTest.php 包含一个基本的模式表单,但没有做任何有用的事情。MemberTest.php 要复杂得多,展示了 NextForm 的许多功能。
请注意,如果您手动创建一个 tests/logs 文件夹,则大多数测试将在此处写入输出。
开发状态
NextForm 仍在积极开发中。截至 2020 年夏末,NextForm 已成功部署在中型应用程序中。随着该应用程序将当前实现的限制推向极限,一些小错误正在得到解决,并正在实现新功能(最值得注意的是插件 Captcha 字段和简化访问控制角色)。测试提供了近 85% 的代码覆盖率。API 应该是稳定的,或者至少任何更改都应该是向后兼容的。请注意,这并不是保证,而是一种意图声明。
NextForm 的下一个渲染目标是 Vue。当前的架构是考虑到这个目标开发的,但实际实施可能会迫使进行一些更改,其中一些可能会影响现有的部署。目前没有时间表。如果您想帮忙,请通过 Gitlab 联系。
NextForm 架构
NextForm 将表单生成分为数据模式、表单定义和渲染引擎。NextForm 还支持字段级访问控制和翻译。NextForm 的数据和模式定义基于 JSON 或 YAML,加载到可以由 PHP 操作的结构中。表单也可以完全用 PHP 定义,从而允许应用程序驱动的表单生成。
模式定义可以在表单上显示的数据的表示和验证信息。模式可以包含多个部分。每个部分通常代表一个数据模型或一个数据库表。分离数据元素允许在多个表单中统一表示和验证这些数据。在一个地方更改定义,NextForm 就会将其更改到每个地方。
表单由元素组成。这些元素可以连接到模式中的数据。在最简单的情况下,表单可以从数据元素列表和一个按钮创建。表单还可以定义事件,定义元素之间的交互。使用此机制,表单元素可以根据用户操作隐藏或显示。
许多应用程序还需要维护多个类似表单的变体。具有访客访问权限的用户在表单上看到的信息可能只包含管理级别表单信息的一个子集,管理员可能能够更改只有管理员才能读取的信息。在大多数情况下,这需要实现多个具有大量重复的表单。NextForm 的灵活基于角色的访问级别访问控制系统允许开发人员为多个用户角色使用一个表单定义。
表单布局概述
表单是一组表单元素。
表单元素可以是简单的或复合的。
简单元素包括静态文本、按钮(提交、重置等)、HTML 以及连接到数据的输入元素。
复合元素有两种类型:单元格和组。单元格包含一组作为单个单元呈现的元素。部分是一组相关字段。部分可以包含单元格,单元格不能包含部分。
所有元素都可以是零个或多个组的成员。组用于根据用户活动启用/禁用和隐藏/显示表单元素。
数据模式概述
模式定义可以组装到表单中的数据对象。
模式提供了基于简单访问控制系统的数据可见性。数据对象可以是读写、只读、隐藏或不存在,具体取决于用户的权限。模式可以从 JSON 或 YAML 文件加载,或由应用程序生成。
每个模式可以包含多个段。目的是将段映射到用于持久化数据的模型或其他数据结构,但这不是必需的。每个段可以包含一个或多个标量对象。
对象必须在段内具有唯一的名称。每个对象可以定义特征,包括存储格式和大小、数据的显示方式、描述该对象的文本标签、可以查看和修改对象的角色等。
翻译概述
NextForm翻译使用Laravel的翻译器接口。具体来说,使用get()方法。不需要翻译实例。如果没有提供,则不会进行翻译。
这应该使适应其他翻译系统变得简单。
访问控制概述
模式中的每个对象都可以定义任意访问角色(或没有任何角色)。
访问权限按优先级排序
- 无。对象不会在表单上显示。
- 隐藏。对象作为隐藏元素嵌入到表单中。
- 屏蔽。对象是可见的,但数据被屏蔽且不可编辑。
- 查看。对象可显示但不可编辑。
- 写入。对象可见并可由用户修改。
角色定义包括一个通配符角色(""),用于定义默认访问级别。如果没有定义任何角色,则默认通配符是":write"。如果定义了其他角色但没有指定通配符,则默认是"*:none"。没有其他规则限制角色名称。对于未明确定义的任何角色的访问请求,将分配由通配符角色给出的访问级别。
角色可以是一个角色名称数组。在这种情况下,返回具有最高访问级别的角色。
示例角色定义
"roles": {
"*": "mask",
"guest": "hide",
"admin": "view",
"owner": "write"
}
角色也可以表示为一个更紧凑的复合字符串。这将产生与上述相同的定义
"roles": "*:mask|guest:hide|admin:view|owner:write"
当将角色作为选项传递给表单渲染引擎时,NextForm将修改生成的表单以匹配角色的规则。
注意:NextForm 1.x包括一个过于复杂的访问控制系统,该系统已弃用。如果没有将角色传递给表单生成,则使用此系统。默认ACL,NullAccess,授予对所有内容的写入权限。
渲染概述
NextForm的模式和表单定义已被设计得尽可能独立于最终输出。通过将此信息与表单实现分离,希望NextForm不仅可以支持像Bootstrap这样的常见HTML/CSS框架,还可以支持Vue这样的客户端JavaScript系统。《code>RenderInterface指定了实现其他环境所需满足的简单要求。
NextForm目前提供两个渲染引擎
- Bootstrap4引擎生成具有事件处理能力的可访问表单。渲染选项支持水平和垂直布局以及自定义功能。
- SimpleHtml引擎生成基本HTML表单,没有原生事件处理。
模式数据结构
在顶级,模式有两个属性,default和segments。
default
default属性指定了所有其他元素的公共值。目前这包括标签。因此,default可以用于为所有对象设置一个公共的错误消息。此消息可以在对象定义中覆盖。
segments
段包含一个名称、一个对象列表、一个可选的构成段中数据主键的对象名称列表,以及其他在此描述的属性。
segments.primary
这是一个包含一个对象名称的字符串或一个对象名称数组。
segments.objects
每个对象具有以下属性
name对象的名称。名称必须在段内唯一。description一个可选的字符串,描述对象。labels定义与对象关联的标签。population如果对象可以取有限集合中的值,例如在单选按钮的情况下,这定义了允许的值。presentation展示描述了在表单上对象的正常表示。store存储描述了存储数据时的格式和大小。validation验证指定了可接受值的规则。
segments.objects.labels
标签可以是简单的字符串或对象。如果标签是字符串,则用作 heading 属性。对象可以有以下属性,所有这些都是可选的
accept当字段通过验证时显示的文本。after紧接输入元素后的文本。例如,如果对象旨在表示整美元金额,这可能是一个 '.00',以帮助用户输入整数。before紧接输入元素前的文本。例如,这可能是一个 'https:' 以指示链接,或 '@' 以表示社交媒体帐户。confirm如果这是一个字符串,则是在此为确认字段时显示的标题。例如 'Confirm password'。如果是对象,则可以具有除confirm之外的所有标签属性。这些字符串将覆盖确认字段上的父字符串。error当用户输入验证失败时显示的文本。heading输入对象的标题。help帮助用户输入值的文本。inner在输入元素内部显示的文本,例如作为占位符。mask覆盖默认掩码字符串(*****)的文本。translate一个标志,指示标签是否要翻译。默认值是 true。
每个文本属性都有一个对应的 HTML 标志,因此例如设置 help.html 为 true 意味着 help 中的文本将作为原始 HTML 处理,而不是转义。
segments.objects.population
一个 population 具有以下属性
list对于固定列表,这是一个选项列表,对象可以采用的可能的值(请参阅 segments.objects.population.option)。sidecar附加到生成代码中对象的任意 JSON 编码字符串。sourcepopulation 的创建方式。目前唯一的有效来源是 'fixed'。可能的值包含在列表属性中。translate一个标志,指示值是否要翻译。默认值是 true。
segments.objects.population.option
population 中的可能值存储在 Option 中。选项具有以下属性
enabled一个标志,指示此选项当前是否可选。默认值为 true。label用户为此选项显示的文本。memberOf此选项所属的组列表。name可选的选项名称,可以在渲染的表单上引用它。sidecar附加到生成代码中对象的任意 JSON 编码字符串。value当在表单提交时选择此选项时返回的值。
选项还支持简写表示法,形式为 "label:value" 的字符串。因此 list: ["One:1", "Two:2", "More:X"] 是一个有效的列表定义。可以在同一列表中混合字符串和对象形式。
segments.objects.presentation
展示指定了对象应该如何在表单上显示。并非所有属性对所有输入类型都适用。任何不适用的属性都将被忽略。一个展示具有以下属性
cols用于显示对象的列数,使用 12 列网格系统。confirm一个标志,指示 NextForm 是否应生成第二个输入以确认用户输入了正确的值。rows显示组合框、文本区域等时使用的行数。type输入类型。可能的值包括:'button'、'checkbox'、'color'、'date'、'datetime-local'、'email'、'file'、'hidden'、'image'、'month'、'number'、'password'、'radio'、'range'、'reset'、'search'、'select'、'submit'、'tel'、'text'、'textarea'、'time'、'url' 和 'week'。
表示方式还可以是一个紧凑的字符串。例如:email|confirm 和 textarea|cols:50|rows:5。组件的顺序不重要,confirm|number 和 number|confirm 是相同的。
segments.objects.roles
可选的“角色”,定义对象对一组任意角色的可见性。如果没有角色,对象将始终具有写入权限。如果有角色,则必须有一个通配符角色("*")来定义默认的访问级别。可以定义其他任何角色以使用以下访问级别之一(无、隐藏、屏蔽、查看或写入)。
详见访问控制概述部分以获取更多详细信息。
segments.objects.store
存储定义了对象如何在存储中持久化。存储具有以下属性
size一个表示对象最大大小的字符串。这通常是整数,但不总是。- `type' 其中一个 'blob'、'date'、'decimal'、'float'、'int'、'string' 或 'text'。
存储也可以表示为一个紧凑的字符串。例如:string|size:200 和 decimal|size:10,2。紧凑字符串部分的顺序不重要。
segments.objects.validation
验证定义了对象的可接受值。验证可以是一个简单的字符串或一个对象。如果labels是一个字符串,则用作 rules 属性。验证属性包括
accept对于文件类型表示,这是一个可接受文件模式的数组capture对于图像或视频类型的文件,设置数据源。maxLength基于文本的输入的最大长度。maxValue基于数值的输入的最大值。minLength基于文本的输入的最小长度。minValue基于数值的输入的最小值。multiple一个标志,表示对象是否可以接受多个值。默认为false。pattern一个定义可接受文本值的 JavaScript 正则表达式。required一个标志,表示该对象需要一个值。默认为false。rules详见以下内容。step数值和范围输入的增量/减量的大小。translatePattern一个标志,表示pattern应该被转换。默认为false。
NextForm v1.3.1 引入了一个 rules 属性到验证对象中,它反映了 Laravel 的验证语法。NextForm 将从规则字符串中提取属性并用于验证。规则定义是不变的,NextForm 未能识别的任何规则保持不变,因此可以将字符串传递给其他验证库。
array导致后续影响minLength、maxLength、minValue和maxValue的规则被忽略。date导致最小和最大规则分别映射到minValue和maxValue。digits设置minLength和maxLengthdigits_between设置minLength和maxLengthfilled映射到required属性设置为 true。integer导致最小和最大规则分别映射到minValue和maxValue。mimes映射到accept属性。每个扩展名ext将*.ext添加到接受列表。nullable将required属性设置为 false。numeric导致最小和最大规则分别映射到minValue和maxValue。regex映射到pattern属性。regex_translate映射到translatePattern属性。string将最小值、最大值、大小和介于之间的规则分别映射到minLength和maxLength。- 所有剩余的验证属性(例如
step)在规则字符串中具有相同的名称。
注意:如果您想保持规则字符串与 Laravel 验证系统兼容,可以保持没有 Laravel 对应规则的规则作为单独的属性,或者扩展 Laravel 以适应 NextForm 规则。
segments.autoLabels
自动标签属性在本地化环境中很有用,这些环境使用对象名称作为翻译消息键的一部分。当提供时,自动标签定义中的星号将被对象名称替换,并应用于段中的每个对象。如果对象已经有标签,则不会覆盖它。
自动标签定义示例
"autoLabels": {
"heading": "*.head",
"help": "*.assist",
}
这将使 name 对象具有标题 "name.head" 和帮助标签 "name.assist"。
表单数据结构
在最简单的情况下,一个表单包含一个名称、一个可选的默认段和一系列对象。这是一个包含三个元素的有效的表单定义。
{
"name": "accessForm",
"useSegment": "accessTest",
"elements": [
"sysId", "username", "phone"
]
}
表单需要一个模式,用于定义每个字段元素。
表单还可以定义其他元素类型
button按钮功能是提交、重置和按钮(链接到某些 JS)captchaNextform 提供插件式 Captcha 接口和基本的本地实现。cell单元格是一个单行容器,用于一个或多个其他元素。单元格不能包含其他单元格或部分元素。htmlHTML 元素直接将内容注入到输出流中。section部分是多行容器,用于其他元素。部分可以包含单元格,但不能包含其他部分。static固定文本,可以是普通文本或原始 HTML,它作为表单布局的一部分出现。
表单上的元素可以覆盖模式中的一些对象属性,例如启用/禁用状态和标签。