Winter / wn-builder-plugin
Winter CMS 的构建插件
Requires
- php: >=7.0
- composer/installers: ~1.0
- nikic/php-parser: ^4.13.2
Requires (Dev)
- phpunit/phpunit: ~4.0
Replaces
- rainlab/builder-plugin: ~1.0
README
一个用户友好的、可视化的插件脚手架工具,使得在 Winter CMS 中运行新插件变得非常简单。此插件通过提供管理插件定义和文件所有方面的几个简单工具,消除了设置插件所需结构的繁琐工作。
安装
您可以使用 Composer 安装此插件。由于这是一个开发插件,应将其定义为“开发”依赖项。
composer require --dev winter/wn-builder-plugin
功能
使用 Builder 插件,您可以
- 创建和更新您插件的数据库模式,并自动生成迁移。
- 定义数据库表的模型。
- 创建和管理控制器。
- 定义您插件的Backend导航项和可用权限。
- 设计和创建您的表单和列表。
- 管理您插件的版本和迁移。
- 在您的 CMS 模板上使用简单的、通用的 Builder 组件显示完整列表和单个记录。
Builder 插件与您的工具和方法完美配合,既全面又谨慎地处理插件修改的范围,让您可以在自己的开发环境中不受 Builder 插件干扰地工作,从而在更复杂的插件功能上工作。
Builder 是一个可视化开发工具。它通过自动化常见开发任务来缩短插件开发时间,使编程再次变得有趣。使用 Builder,您可以在几分钟内创建一个功能齐全的插件脚手架。
Builder 通过提供可视化界面,自然地结合了 Winter 的设计模式和文档,使学习曲线更加平缓。例如,您不需要查阅文档中的支持表单控件及其功能的列表,只需打开表单构建器,在控件调色板中找到合适的控件,将其添加到表单中,并使用可视化检查器探索其属性即可。
Builder 通过自动化无聊的活动来实现快速应用开发过程,同时不牺牲完全的控制。使用此工具,您可以在您喜欢的代码编辑器中花更多时间实现插件的业务逻辑,而不是处理更平凡的任务,如构建表单或管理插件版本。
使用 Builder 创建的插件与您通常手动创建的插件没有区别。这意味着您可以使用您常用的“动手”工作流程来更新服务器、管理代码版本以及与队友共享工作。
视频教程
查看 https://vimeo.com/154415433 中的视频教程,了解如何使用此插件构建一个简单的图书馆插件。
Builder 可以做什么
此工具包括多个功能,涵盖了创建插件几乎所有的方面。
- 初始化新插件 - 这将创建插件目录以及任何必要的文件。
- 创建和编辑插件数据库表。所有模式更改都保存为常规迁移文件,因此您可以使用常规工作流程轻松地在其他服务器上更新插件。
- 创建模型类。
- 使用可视化表单构建器创建后端表单。
- 创建后端列表。
- 管理由插件提供的用户权限列表。
- 创建插件后端导航 - 以主菜单项和侧边栏项的形式。
- 使用可视化工具创建后端控制器并配置其行为。
- 管理插件版本和更新。
- 管理插件本地化文件。
- 一组通用组件 - 用于在前端以列表和单条记录详情的形式显示插件数据。
简单来说,您可以创建一个多语言插件,该插件安装数据库表,具有受用户权限保护的后端列表和表单,并为显示由插件管理的数据添加CMS页面。学习Builder的工作原理后,这个过程只需几分钟。
Builder是一款生产力工具,它并不完全替代手动编码,也不包含用于编辑PHP文件的代码编辑器(唯一的例外是版本管理界面)。Builder永远不会覆盖或删除插件PHP文件,因此您可以放心,您编写的代码永远不会被Builder修改。然而,Builder可以创建新的PHP文件,如模型和控制器。
Builder中的大多数可视化编辑器都与YAML配置文件一起工作,这是Winter CMS的本地概念。例如,在Builder中创建一个模型类后,您可以选择向模型添加表单。这个操作会在模型的目录中创建一个YAML文件。
在使用Builder时目前存在一些限制。其中一些是将来将添加的功能。其他是一些为了保持简单而故意省略的想法。如上所述,Builder不想取代编码,同时也不走得太远进行可视化编程。这些限制在插件文档的相关部分中有解释和描述。这些限制并不意味着您不能创建任何插件 - 对于使用Builder开发的插件,始终适用编写代码的古老方法。Builder的目标是成为一个谦逊但强大的工具,用于加速您的开发周期。
入门
在您使用Builder创建第一个插件之前,应该对其进行配置。在Winter CMS后端打开设置页面,并在侧菜单中找到Builder。输入您的作者姓名和命名空间。作者姓名和命名空间是必填字段,如果您希望在Winter CMS Marketplace上发布插件,则不应更改。
如果您已经有了一个Marketplace账户,请使用您现有的作者姓名和命名空间。
初始化新插件
在Winter CMS后端的Builder页面中,点击侧边栏中的小箭头图标以展开插件列表。单击“创建插件”按钮后,输入插件名称和命名空间。默认作者名称和命名空间可以从插件设置中预先填充。选择插件图标,输入描述文本和插件主页URL(可选)。
请注意,创建插件后,您不能更改命名空间。
当Builder初始化插件时,它会在Winter的plugins目录中创建以下文件和目录
📂 myauthor /* Author name */ ┗ 📂 myplugin /* Plugin name */ ┣ 📂 lang /* Localization files */ ┃ ┗ 📂 en /* Specific locale folder */ ┃ ┗ 📜 lang.php /* Translations */ ┣ 📂 updates /* Database migrations */ ┃ ┗ 📜 version.yaml /* Changelog */ ┣ 📜 Plugin.php /* Plugin registration class */ ┗ 📜 plugin.yaml /* Basic plugin information in YAML format in order to edit with Builder */
plugin.yaml文件包含基本插件信息 - 名称、描述、权限和后端导航。此文件由Builder用户界面管理。
lang.php本地化文件的初始内容是插件名称和描述。本地化文件是在Winter安装的默认区域设置中创建的。
当创建新插件时,它将自动作为Builder正在处理的当前插件选中。如果您需要,您可以在插件列表中选择另一个插件。
管理插件数据库表
在Builder的数据库选项卡上管理表。您可以使用可视化界面创建表、更新其结构和删除表。
单击“添加”按钮以打开“创建表”选项卡。Builder会自动为插件表生成前缀。这些前缀符合开发者指南中的数据库表命名规范。
每次在表格中保存更改时,Builder都会显示一个包含自动生成的迁移PHP代码的弹出窗口。您无法在弹出窗口中编辑代码,但可以检查它或将其复制到剪贴板。在审查迁移后,单击“保存并应用”按钮。Builder将立即执行迁移并将迁移文件保存到插件更新目录。之后,您可以在Builder的版本选项卡中找到所有插件迁移。
注意:虽然Builder可以自动生成迁移文件,但在您显著更改表结构的情况下,它无法防止某些情况下的数据丢失。例如,在更改字符串列的长度时,这可能发生。在应用迁移之前,请始终检查Builder生成的迁移PHP代码,并考虑在生产数据库中运行迁移的可能后果。
目前,Builder不允许您通过可视化用户界面管理表索引。尚未支持唯一列管理。请使用版本管理功能手动创建迁移文件。
请注意,由于底层Doctrine类的限制,Builder目前不支持enum
数据类型。
管理模型
您可以在Builder的“模型”选项卡中编辑模型。单击“添加”按钮,输入模型类名称并从下拉列表中选择一个数据库表。
模型类名称不应包含命名空间。例如:Post、Product、Category。
注意:由于它违反了不使用可视化工具删除或覆盖PHP文件的理念,因此您无法使用Builder删除模型文件。如果您需要删除模型,请手动删除其文件。
管理后端表单
在Winter CMS中,表单属于模型。对于每个模型,您可以根据需要创建多个后端表单,但在大多数情况下每个模型只有一个表单。
注意:当您创建表单时,它不会在Winter CMS后端显示,直到您创建一个使用该表单的后端控制器。有关控制器的更多信息,请参阅下面的内容。
在Builder的“模型”选项卡中找到一个要创建表单的模型。如有必要,展开模型,悬停在“表单”部分,然后单击加号。
Winter CMS中的表单使用YAML文件定义。默认表单文件名为fields.yaml。在表单构建器中,单击占位符并从弹出列表中选择一个控件。之后,您可以在检查器中单击控件并编辑其参数。
几乎所有表单控件都具有这些常见属性
- 字段名称 - 模型字段名称。它是检查器中的自动完成字段,允许您从底层数据库表中选择列名称。目前,关系尚未在自动完成提示中显示,这将在以后实现。您可以手动输入任何模型属性。
- 标签 - 控件标签。您可以将静态文本字符串输入到字段中,或通过单击输入字段中的加号创建新的本地化字符串。Builder中的几乎所有编辑器都支持此功能。
- 注释 - 注释文本 - 固定文本或本地化字符串键。
- 跨度 - 控件在表单上的位置 - 左、右、全或自动定位。
大多数属性都具有描述性的名称或具有检查器中的说明。如果您需要有关控件属性的更多信息,请参阅文档。
您可以在表单构建器中拖动控件以重新排列它们或将它们移动到/从表单选项卡中。
注意:表单选项卡至少应有一个控件,否则在表单构建器保存YAML文件时将被忽略。
注意:一些表单控件,例如文件上传控件,需要在模型类中手动创建一个关系。关系名称应在字段名称属性中输入。有关特定表单控件的详细信息,请参阅表单文档。
管理后端列表
与表单类似,Winter CMS 中的后端列表属于模型。
注意:在创建列表后,除非您创建一个使用该列表的后端控制器,否则 Winter CMS 后端不会显示该列表。请参阅下文关于控制器的说明。
在 Builder 的“模型”标签页中找到您想要创建列表的模型。如有需要,展开模型,悬停在“列表”部分并点击加号。
Winter CMS 中的列表使用 YAML 文件定义。默认列表文件名为 columns.yaml。列表编辑器中的网格包含列表列定义。列属性名称具有自描述性,尽管其中一些需要一些解释。有关每个属性的详细信息,请参阅列表文档。
对于“标签”属性,您可以选择输入静态字符串或创建一个新的本地化字符串。
“字段”属性列具有自动完成功能。它允许您从绑定到模型的数据库表中选择列。目前它不显示关系属性,但您仍然可以手动输入它们。
管理插件权限
插件权限定义用户可以访问的功能和后端插件页面。您可以在 Builder 的“权限”标签页中管理权限。对于每个权限,您应指定一个唯一的权限代码、权限标签页标题和权限标签。标签页标题和标签在 October 后端的“系统”页面上的用户管理界面中显示。
对于标签页标题和标签,您可以选择输入静态字符串或创建一个新的本地化字符串。
稍后,当您创建控制器和菜单项时,您可以选择用户访问或查看这些对象的权限。
管理后端菜单
在 Builder 的“后端菜单”标签页中管理插件导航。用户界面允许创建顶级菜单项和侧边栏项。
要创建菜单项,请点击占位符矩形,然后点击新项以打开检查器。在检查器中,您可以输入项标签、选择图标并分配用户权限。对于从控制器代码中引用菜单项(用于标记菜单项活动),code属性是必需的。
注意:当您为插件中尚未存在的后端页面创建菜单项时,在创建插件控制器之前留空 URL 属性是有意义的。此属性支持自动完成,因此您可以从下拉列表中选择您的控制器 URL。
管理后端控制器、表单和列表
Winter CMS 中的后端页面提供后端控制器。通常后端页面包含用于管理插件记录的列表和表单,尽管您可以创建任何自定义控制器。
请参阅后端表单、列表和排序控制器的文档页面,以获取有关控制器行为的更多信息。目前,只有列表、表单和排序控制器行为可以使用 Builder 进行配置。如果您的控制器包含其他行为,它们不会被 Builder 删除,但您将无法使用可视化界面编辑它们。
Builder 还允许您创建不实现任何行为的空控制器类,并手动对其进行自定义。
注意:一些行为需要实现特定的模型功能。例如,排序控制器行为要求模型实现 Sortable 或 NestedTree 特性。始终参考特定行为的文档以获取实现细节。
要创建控制器,请点击“控制器”选项卡上的“添加”按钮列表。输入控制器类名,例如Posts。
如果控制器将要提供后端列表或表单,请从下拉列表中选择一个基础模型,并选择您要添加的行为。您还可以选择控制器页面应激活的顶部和侧边菜单项。如有需要,选择用户必须拥有的权限才能访问控制器页面。
请注意,在“创建控制器”弹出窗口中输入的设置无法使用Builder进行更改。但是,您可以手动通过编辑控制器类来更新它们。
创建控制器后,您可以配置其行为。在列表中点击控制器,然后点击您要配置的行为。当Builder创建控制器时,它会尝试将默认配置应用到行为上,但是您可能想要更改它。检查器列表显示所有支持的行为属性。URL属性(如列表记录URL)是自动完成字段,并填充现有插件控制器的URL。
管理插件版本
请阅读版本历史文档页面,了解Winter CMS中版本如何工作。
基本上有3种类型的版本更新
- 更改数据库结构的更新 - 迁移。当您在数据库选项卡上更改DB架构时,Builder可以自动生成迁移文件。
- 填充数据库内容的填充更新。
- 版本更新,它不更新数据库中的任何内容,但常用于发布代码更改。
在Builder的“版本”选项卡上管理插件版本。此选项卡显示现有插件版本及其状态。已应用版本有绿色复选框标记。挂起的版本有灰色时钟标记。
您可以单击“添加”按钮并选择更新时间来创建新版本。用户界面自动生成用于“迁移”和“填充”更新的scaffold PHP代码。“增加版本号”更新不会包含任何PHP代码。
对于每个版本,您应指定新的版本号和描述。Builder自动通过增加现有版本的最后一位数字来生成版本号。如果您正在发布主要版本更新并希望更改第一位或第二位数字,则可能需要更改它。
保存版本文件时,Builder不会立即应用它。您应该在工具栏中单击“应用版本”按钮来应用版本并执行更新代码(如果适用)。您还可以回滚已应用的版本更新,更改其代码并再次应用。这允许您编辑Builder生成的默认代码的数据库架构更新。
请注意,您的迁移文件应在
down
方法中提供正确的回滚代码,以便使用回滚功能。
当您回滚一个版本时,它会自动回滚所有较新版本。当您应用一个版本时,它会自动应用所有挂起的较旧版本。请记住,当用户登录到后端时,October会自动应用所有挂起的更新。切勿在生产服务器或具有多个后端用户的服务器上编辑版本 - 这可能导致不可预测的后果。
不支持包含多个脚本的迁移。它们无法使用Builder创建或编辑。
管理本地化
本地化文件在Builder的“本地化”选项卡上管理。当初始化新插件时,会创建一个单独的语言文件。此文件在Winter CMS配置脚本中指定的默认系统区域设置中创建。
您可以创建任意数量的语言文件。Builder UI始终在Winter CMS区域设置中显示字符串,因此您可能希望更新您的配置文件以在另一种语言中查看您的插件。
请注意,尽管Winter CMS中的本地化文件是PHP脚本,但为了简化Builder用户界面的编辑,它们被转换为YAML格式。当保存语言文件时,它们会被再次转换为PHP格式。
Builder会尝试使用户界面与您的默认语言文件保持同步。这意味着当您保存语言文件时,Builder会自动更新所有编辑器中的所有本地化字符串。在某些情况下,您可能需要关闭并重新打开检查器以重新初始化自动完成字段。
在许多情况下,您可以直接从Builder编辑器(如表单构建器、菜单构建器等)创建新的本地化字符串。本地化输入字段右侧有一个加号图标。点击加号图标会弹出一个窗口,允许您输入本地化字符串键和值。字符串键可以包含点来标记本地化文件部分。例如 - 如果您添加一个键为plugin.posts.category
、值为"输入分类名称"的字符串,Builder将在语言文件中创建以下结构
plugin: posts: category: Enter a category name
如果您在Builder中打开默认语言文件标签页时,从检查器或其他编辑器创建新的本地化字符串,它将尝试更新标签页内容或合并来自服务器的更新文件内容。建议始终在Builder中保存默认本地化文件,以避免在从其他地方编辑本地化时可能出现的冲突。
技巧:在YAML中,单个引号用两个单引号转义(https://yaml.org/spec/1.2.2)。
在前端页面上显示插件记录
Builder提供通用的CMS组件,您可以使用这些组件在网站前端页面上显示插件记录。这些组件仅提供基本功能,例如,它们不支持记录搜索功能。
请阅读CMS文档以了解有关CMS组件概念的更多信息。
记录列表组件
记录列表组件输出由插件模型提供的记录列表。该组件支持以下可选功能:分页、记录详情页的链接、使用模型作用域进行列表过滤。列表可以按任何列排序,但排序不能由网站访客更改 - 它由组件配置设置。
通过从组件列表中将此组件拖放到CMS页面代码中并将其点击,将其添加到CMS页面
模型类
- 选择您想从数据库中获取数据的模型类。作用域
- 可选,选择用于过滤结果的模型作用域方法作用域值
- 可选,为所选作用域方法提供的值。URL参数可以以{{ :nameOfParam }}
的形式提供显示列
- 选择要在列表中显示的模型列。这是一个自动完成字段,显示底层数据库表中的列。您可以在该字段中输入任何值。该值用于默认组件部分,您可以通过提供自定义标记而不是默认部分来自定义组件。详情页
- 您想创建链接的CMS页面的下拉列表。详情键列
- 选择用作记录链接中记录标识符的列。您可以通过主标识符(id)、slug列或其他任何方式链接您的记录 - 这取决于您的数据库结构。URL参数名称
- 输入详情页URL参数名称,该参数用于记录标识符。例如,如果记录详情页的URL类似于 "/blog/post/:slug",则URL参数为 "slug"。每页记录数
- 输入一个数字以启用记录分页。页码
- 指定固定的页码或使用 外部参数编辑器 输入包含页码的URL参数名称。例如 - 如果您的记录列表页面的URL为 "/record-list-test/:page?",则页码属性值将是 ":page"。排序
- 选择用于排序列表的数据库列名称。方向
- 选择排序应为升序还是降序。
配置组件后保存并预览页面。您可能希望自定义 默认组件标记 以输出每个记录的更多详细信息。
记录详情组件
记录详情组件从数据库加载模型,并在页面上输出其详细信息。如果找不到请求的记录,组件将输出“记录未找到”消息。
通过从组件列表中将此组件拖放到CMS页面代码中并将其点击,将其添加到CMS页面
模型类
- 选择您想从数据库中获取数据的模型类。标识符值
- 指定一个固定值或使用 外部参数编辑器 输入URL参数的名称。如果详情页的URL类似于 "/blog/post/:slug",则标识符值将是 ":slug"。键列
- 指定用于查找记录的数据库表列的名称。这是一个自动完成字段,显示底层数据库表的列。显示列
- 输入要在详情页上显示的数据库表列的名称。该值用于默认组件部分,您可以通过提供自定义标记而不是默认部分来自定义组件。未找到消息
- 如果未找到记录,则显示的消息。在默认部分中使用。
配置组件后保存并预览页面。您可能希望自定义 默认组件标记 以输出加载的模型的更多详细信息。
关于自动完成的说明
Builder每次在底层数据更新时都会更新检查器自动完成字段。例如,表单构建器的“字段名称”属性会填充数据库表列名称。如果您使用Builder更新表结构,自动完成缓存将自动更新。但是,您可能需要重新打开检查器,以便它可以更新其编辑器。
如果您使用外部编辑器编辑插件文件或数据库结构,Builder将无法自动获取这些更改。您可能需要在添加数据库列后重新加载Builder页面,以刷新自动完成功能。
编辑其他插件
尽管Builder允许您编辑其他作者创建的插件,但请记住,您这样做是自行承担风险的。插件可能会被其作者更新,这可能会消除您的更改或破坏插件。在许多情况下,如果您更新其他作者开发的插件,您将失去作者提供的任何技术支持。
添加对自定义FormWidget的支持
要将自定义小部件添加到Builder插件中,您必须首先为您的插件 注册后端表单小部件。
注册后,在您的插件中的插件注册类 boot()
方法中定义属性列表,并注册自定义控件。例如
public function boot() { $properties = [ 'max_value' => [ 'title' => 'The maximum allowed', 'type' => 'builderLocalization', 'validation' => [ 'required' => [ 'message' => 'Maxium value is required' ] ] ], 'mode' => [ 'title' => 'The plugin mode', 'type' => 'dropdown', 'options' => [ 'single' => 'Single', 'multiple' => 'Multiple', ], 'ignoreIfEmpty' => true, ] ]; Event::listen('pages.builder.registerControls', function($controlLibrary) { $controlLibrary->registerControl( 'yourwidgetname', 'My Widget', 'Widget description', ControlLibrary::GROUP_WIDGETS, 'icon-file-image-o', $controlLibrary->getStandardProperties([], $properties), 'Acme\Blog\Classes\ControlDesignTimeProvider' ); }); }
注意:有关更多示例,请参阅
winter/builder/classes/ControlLibrary.php
文件中的getStandardProperties()
方法。
现在,我们需要上面引用的 ControlDesignTimeProvider
类。将以下内容保存为您的插件目录中的 classes/ControlDesignTimeProvider.php
(使用您在插件注册类 boot()
方法中使用的 'yourwidgetname'
替换)。
<?php namespace Acme\Blog\Classes; use Winter\Builder\Widgets\DefaultControlDesignTimeProvider; class ControlDesignTimeProvider extends DefaultControlDesignTimeProvider { public function __construct() { $this->defaultControlsTypes[] = 'yourwidgetname'; } }
然后将以下内容保存为插件目录下的class/controldesigntimeprovider/_control-yourwidgetname.htm
,并按需进行自定义。再次强调,文件名中的yourwidgetname
必须与
<div class="builder-blueprint-control-text"> <?= e(trans('acme.blog::lang.mywidget.placeholder')) ?> </div>
现在您应该能够在Builder插件中添加和配置您的自定义小部件,就像其他插件一样。