构建组件的工具 - 2:嵌入式应用程序
在我们构建工具冒险系列的第二集中,我们将更深入地探讨我们的活动日程示例,并探索如何使用两个 Joomla 应用程序构建器——Seblod 和 Fabrik 来实现它。我们不会创建一个完整的组件,而是将应用程序嵌入到这些扩展中。通过这样做,我们还将更好地理解在系列文章的后续文章中想要构建的组件的需求。
我们的旅程到目前为止
在第 一集 中,我们介绍了一个活动日程,例如 JoomlaDagen 的日程,作为一个示例。我们展示了如何使用 Joomla 的核心功能构建一个基本的活动日程应用程序,而不需要创建自定义组件。我们使用了 附加字段 (1) 来增强核心内容类型,如文章和分类。
我们通过指定 实体 和它们的关系来分析我们的活动日程示例。
我使用了一些来自原始 JoomlaDays 2024 日程的数据,在我们的实施中,带有附加字段的日程看起来像这样
我的演讲者概述看起来像这样
模板布局的详细信息可以在 此系列的存储库 中找到。
值对象
在我们的活动日程示例中,我们有以下概念:
- 一个包含日程/计划的页面:一个 容器。
- 一个或多个用于安排事件的“轨道”:一个 部分(多个部分可以同时安排事件,在相同的时间)。
- 一些发生的事情,例如一个演讲:一个 事件。
- 一个对象,它定义了事件在哪里以及何时发生:一个 位置。
- 进行事件的人,例如一个演讲者或一个乐队:一个 演员。
我们将所有这些基本构建块称为“实体”。但在我们的实施中,实际上我们只创建了事件和演员作为实体,并且它们有自己的 id。
实体是由独特身份特征定义的对象。即使它们的属性发生变化,它们仍然是同一个实体。它们通常由一个唯一的标识符来表示。值对象((2))另一方面,没有独特的身份。它们完全由它们的值来定义。如果两个值对象具有相同的值,它们被认为是相等的。
定位器对象只是一系列值;一个值对象,而不是实体。事件实体可以包含零个或多个定位器对象,以定义事件发生的地点和时间。在第一集中,容器和部分被实现为一系列固定的值(“枚举”);这些值被设置为选择字段的选项。
以下是我们的示例中两个实体的事实上在第一集中实现的实体关系图(ERD)
定位器对象是事件实体的一部分。图中的< strong>菱形在连接线的一端表示这一点。“0..n”标记表示一个事件可以包含零个或多个定位器。这在第一集中通过一个非必填的多子表字段实现。
更多实体
我们希望能够以标准内容管理方式管理容器和部分的可能值:在它们自己的表中添加、编辑和删除它们。因此,我们将它们作为独立的内容类型,再次作为独立的实体。我们还想添加有关哪些容器可以用于哪些部分的信息。
为了方便起见,在第一集中我们使用了标签来表示事件类型。标签已经作为基础文章内容类型的一个字段可用。缺点是我们必须在另一个地方(标签组件)中定义这些标签,而实际上只在我们自己的应用程序中使用它们。软件设计中的一个良好原则是将属于一起的东西放在一起。这就是为什么我们将为事件类型创建一个独立的实体。一个事件只能有一个事件类型。
我们的实体关系图(ERD)现在看起来像这样
多对多
在我们的模型中,演员和事件有一个“多对多”的关系,这意味着一个事件可以由多个演员执行,一个演员也可以执行多个事件。在第一集中,我们实现了演员字段(在事件实体中)和事件字段(在演员实体中)作为一个多选,从所有可能的演员或事件中选择。但是,这两个选择之间没有真正的联系:如果你向一个演员添加一个事件,那么那个演员不会自动在事件的事件演员字段中被选中。你将不得不在两个方向上定义这些联系。信息是“冗余”的,可能不一致。
在规范化的((3))关系数据库中,多对多关系通过一个额外的“连接”表来实现。这个连接表结合了事件表和一个演员表的关键。
在Seblod中,我像上一集那样实现了这个关系:在两个方向上添加关系。在Fabrik中,我通过连接表实现它,正如我们将在下一集中做的那样,当我们最终创建一个“真实”组件时。
通用变量
在第一集中,我们为事件时间表创建了一些通用变量作为事件时间表类别的附加字段。当我们构建一个组件时,我们可以将这些变量作为组件的参数来构建。目前,我们将它们放在一个额外的表中。
内容构建和应用构建器
Fabrik 是一个用于构建自定义应用程序的 Joomla 组件。它已经存在了一段时间:Fabrik 1.0 于 2007 年发布,用于 Joomla 1.0((4))。它专注于构建用于 Joomla 前端的应用程序,定义表单、字段(“元素”)、列表和布局(“可视化”)。Fabrik 自动创建应用程序内容的自定义、规范化的表。
当2007年发布Drupal 5.0时,它引入了一个“内容构建工具包”(CCK),这是一个工具,使用户可以直接从后端创建自定义内容类型。当时Joomla的方法主要集中在为新的内容类型开发自定义组件。从大约2009年开始,为Joomla构建了多个CCK,如FlexiContent、K2、Zoo、Seblod、Cobalt和TF Content。在2010年和2013年之间的炒作之后,对Joomla的CCK的兴趣有所下降,您可以在Google趋势中看到这一点(5)
Joomla 3.1(2013年4月)开始添加了一个针对不同内容类型的核心解决方案:统一内容模型(UCM)(6)。它用于一些核心功能(7),但从未取得真正的成功。在Joomla 4(8)中,它被放弃,但仍然留下了它的痕迹。自Joomla版本3.7(2017年)以来,核心中集成了额外的字段,这些字段提供了CCK所需的许多功能。
除了Fabrik,我们在这个系列的第一集中还将只探讨另一个CCK/应用程序构建器:Seblod。选择Seblod而不是所有可能的CCK是非常随机的。在另一个CCK中实现我们的事件日历可能会给出一些不同的结果。我的意图不是全面,而是展示一个用CCK构建的应用程序在核心实现和组件之间。
我们在这个系列的前两集中所走的路
- 集1:扩展现有文章和分类表以添加额外字段,扩展现有核心内容类型。
- 集2:使用应用程序构建器来添加新的内容类型。应用程序运行在应用程序构建器“之下”,嵌入到Seblod或Fabrik中。
在这篇文章中,我们只能触及Seblod和Fabrik的表面。我们将展示一些在不构建组件的情况下实现我们的事件日历示例的可能性,这比仅使用核心功能更高级。Fabrik、Seblod和其他内容构建工具包应在这本杂志中拥有自己的文章,以充分展示它们的性能(9)。
Seblod
文档:https://www.seblod.com/resources/manuals。
暗色模式使选项卡的标题不那么易读,因此截图是在亮模式下。
我在Seblod中实现我们的事件日历示例所采取的步骤
1 - 创建应用程序文件夹
导航到Seblod核心 > 应用程序文件夹,然后在顶层 > SEBLOD > 应用程序下使用“+ 新建”按钮创建一个应用程序文件夹“事件日历”。
2 - 创建内容类型和表单
导航到Seblod核心 > 表单 & 内容类型,并将标签为'任何应用程序文件夹'的下拉菜单设置为'事件日历'。为我们的实体(容器、部分、事件、事件类型和演员)创建新的内容类型。在每个实体中设置“应用程序文件夹”为“事件日历”。
在Seblod中,通常将“内容对象”设置为“文章”。这样,我们的起点将是com_content中的文章,就像我们在第一集中做的那样。所有无法映射到文章内容类型字段的额外字段将存储在额外的表中(#__cck_store_form_<content-type名称>)。
因为在我们下一集中,我们将创建一个具有自己表格的组件,所以我现在在Seblod中也把所有字段放入了各自的表格中。我保留了Seblod为表格命名的名称(# __cck_store_form_内容类型名称),但我本可以用其他表格名称。我是在PhpMyAdmin中创建的表格,并为它们添加了一个自增的id字段。
如果你从未做过这件事,不要因此感到气馁:在Seblod中,当你只处理Joomla文章作为基本内容对象时通常更容易。但如果你想学习如何创建自己的组件,那么与数据库和PhpMyAdmin一起玩耍是一个很好的时间投资。
当我们使用自己的表格而不是# __content表格时,我们将“内容对象”设置为“自由”。
使用右侧面板上的+按钮为实体创建字段,例如为容器使用“container_name”。
默认情况下,所有创建的字段都放在“管理表单”模板中,但你可以通过单击“站点表单”按钮轻松地将它们放入前端表单。然后您可以通过拖放将字段放入其中。此类前端表单可用于商业目录或调查表单。在使用前端表单时,不要忘记添加提交按钮。
在类型下拉菜单中,您可以选择要创建的字段类型。一些常见类型(就像在Joomla的其他地方一样)有:
- 文本:简单的文本输入字段
- Wysiwyg编辑器:带编辑器的多行字段
- 选择数字
Seblod有一个很好的图像上传字段,可以自动生成缩略图。Seblod商店中还有更多字段类型。
3 - 创建定位器重复组
定位器是一组可以重复的事件值。这可以通过GroupX字段来实现。
4 - 添加到其他内容类型的链接
使用“选择动态”字段创建与另一个相关实体连接的下拉列表。例如,对于属于事件类型的事件。也可以是多选,例如选择属于某个部分的容器:
在Seblod商店中有一个级联动态选择字段可供使用(20欧元),它是使用Ajax动态填充的。
5 - 创建列表
导航到Seblod核心 > 列表 & 搜索类型,创建所有实体的列表。这些列表也将出现在Seblod Apps管理员菜单项下,因此您可以在后端编辑数据。
6 - 创建日程安排模板
您可以使用“拖放模板”将所有变量放入模板中。我不得不制作一个新的Seblod列表模板来显示我们的活动日程。它是基于我们在第一集制作的重写博客布局。这些模板就像任何其他Joomla模板一样通过Joomla安装程序安装。我的自定义模板和更多详细信息可以在本系列的存储库中找到。安装后,导航到Seblod核心 > 模板以将模板用作列表模板。列表模板可以通过创建菜单项来显示在网站上。
导出
Seblod应用可以轻松导出(并将导出的应用导入到另一个具有Seblod的网站)。转到Seblod核心 > 应用文件夹,然后点击“事件日程”应用所在行的三个点;您将看到一个“下载此应用”链接
您将获得一个 app_cck_event_schedule.zip导出包,该包可以使用Joomla扩展管理器(在已安装Seblod的网站上)简单安装。您还可以在包中导出菜单项。如果您也想从您的应用程序中导出数据 ,则有一个SEBLOD导出器插件可用(€ 20)。 在Seblod商店中还有一些完整的包。
Fabrik
文档:https://fabrikar.com/forums/index.php?wiki/
我在Fabrik中实现我们事件日程示例所采取的步骤
- 为实体创建表单 。
- 为定位对象创建一个组 。
- 为所有组创建元素 。
- 创建多对一关系。
- 创建多对多关系。
- 为列表创建菜单项。
- 创建数据的“可视化”。
1 - 创建表单
为所有实体和一般参数创建表单。在表名前加上前缀(我使用了“afab_eventschedule_”),否则您只会得到“容器”、“部分”等表。
让Fabrik自动创建一个具有相同名称的组。
2 - 创建额外的组
为定位对象创建一个组。将此组添加到事件表单中。然后返回定位组,并使其可重复。
3 - 为所有组创建元素
Fabrik将字段称为'元素'。为所有组创建元素。所有实体表都已自动创建id。还有一个用于最后修改日期的时间,但如果您不感兴趣,可以删除它。所有元素都将自动添加到数据库中的表中。
4 - 创建多对一关系
在定位对象中,我们选择一个容器和一个部分,并在事件实体中选择一个事件类型。这些都是通过“databasejoin”字段实现的下拉选择。只需在相应的组中创建一个新字段(容器、部分和event_type),字段类型(=插件): = databasejoin,然后从连接表中获取id和名称
5a - 单向多对多关系
当您只想从一侧使用多对多关系时,可以使用databasejoin字段,就像我们在多对一关系中所做的那样。例如,在我们的部分中,我们显示一个字段来选择可以在此部分中使用的多个容器,但在我们的容器中,我们不使用此类字段来显示所有可用于该容器的部分。现在唯一的区别是我们使用多选下拉列表来选择我们的容器
在幕后,Fabrik也会在那种情况下创建一个连接表,即“section_repeat_containers”表
在我们的JoomlaDagen示例中,所有房间(部分)都在两天(容器)中都可用。但其他日程安排不一定如此。为了正确实现这一点,我们最好使定位器中的容器和部分下拉列表级联,以便在选择第一个下拉列表中的容器时,我们只看到第二个下拉列表中可用于该容器的部分。Fabrik有级联下拉列表字段用于此。
5b - 双向多对多关系
但现在我们想在演员实体中添加一个事件字段来选择演员执行的事件,并在事件实体中添加一个演员字段来选择执行此事件的所有演员。因此:真正的双向多对多关系。这需要几个步骤
- 创建演员-事件连接表。在 Fabrik 中,您通过创建一个演员-事件表单,并自动创建一个同名组、列表和表格(只需添加“afab_eventschedule_”前缀)来完成此操作。
- 在演员-事件组中创建元素(=字段)actor_id 和 event_id。
- 创建两个列表连接:在事件列表中,从 event.id 到 actors-events.event_id 创建一个连接,在演员列表中从 actor.id 到 actors-events.actor_id 创建一个连接。在这两种情况下,将连接设置为重复。
- 您将得到两个重复组,我将它们重命名为 Actor_Events(表示演员实体中的事件)和 Event_Actors(表示事件实体中的演员)。
在这些重复组中,您可以找到我们的连接表记录:actor_id 和 event_id 的配对。在一个演员实体中,我们对该记录的 actor_id 不感兴趣,因此我们隐藏它。
对于 Event_Actors 组中的 event_id 也是同样的情况。
- 最后,我们希望看到所选事件和演员的名称,而不是它们的 ID。我们知道这个技巧:我们将 event_id 和 actor_id 的字段类型更改为通过分别使用数据库连接字段与事件表和演员表连接来获取名称。以下是 Actor_Events 重复组中我们的 event_id 的截图
本质上,这些步骤可以归结为
- 从连接表中获取相关实体的 ID。
- 将那些 ID 解析为相关实体(或属性,如它们的名称)。
下一期我们将也在我们的组件中这样做。
11 - 创建菜单项
使用 Fabrik 在后端添加内容是可能的,但它更多地是针对在前端使用我们的列表和表单。为列表创建菜单项,限制使用者为超级用户(或特殊组)。因此,您需要在前端登录才能添加内容。
13 - 创建数据的“可视化”
我们需要为我们的计划创建一个时间表,使用我们在内容类型中放入的元素。
导出
从版本 4 开始,不再为 Fabrik 应用程序“包”提供导出。
计划输出
我们在前两期中使用的前三种方法(核心附加字段、Seblod 和 Fabrik)的输出是相同的,因为我们基本上使用了相同的模板布局来安排计划。在下一期创建 Joomla 组件时,我们也将获得相同的输出。
要点
我们在前两期中展示的一些方面
- 将数据分析为 实体 和 值对象。
- 实体之间的关系 以及在正常化的关系数据库中使用双向多对多关系时需要 连接表 的需求。
- 您可以通过坚持使用完全 正常化数据库 来实现相同的结果,就像 Fabrik 所做的那样,或者通过在字段中放入多个值来实现,就像核心附加字段和 Seblod 所做的那样。两者都有优点和缺点。在我们的组件中,我们将回到这个设计决策。
遗漏
我们到目前为止遗漏的,但会使我们的应用程序更成熟的内容
- 验证 和限制输入。我们应用程序的一个“业务规则”是:一个计划(轨道)中不应有重叠的事件。同样:一个演员不能同时出现在两个地方。
- 计划 过程。我们现在为每个事件填写位置对象,但我们最好有一些关于哪些事件尚未安排以及如何将它们放入计划的概述,最好使用拖放。然后:从开始时间 + 持续时间自动计算结束时间。
- 应用 测试。它是否正确工作,包括边缘情况?
下个月:一个真正的组件!
系好安全带,下个月我们将终于为我们的活动日程示例构建一个Joomla组件。我们将展示如何制作自己的组件,并解释一些基本模式,如模型-视图-控制器和依赖注入。我们还将展示一些更高级的功能,例如实现非冗余的多对多关系。敬请关注,让您的Joomla开发技能提升到下一个层次!
注释
- 在第一集中,我解释了为什么使用“附加字段”而不是“自定义字段”这个词。
- 来自“《领域驱动设计:解决软件复杂性》”,埃里克·埃文斯,2004年
- 在规范化关系数据库中的一个字段仅包含单个值,且不会存储重复信息(“冗余”)。参见例如https://en.wikipedia.org/wiki/Database_normalization和https://www.databasestar.com/database-normalization/
- 参见Fabrik 1.0手册和Rob Clayburn访谈,均为2007年。
- 正如您在Google Trends中将Fabrik与FlexiContent进行比较时所见,对Fabrik的兴趣也有所下降:
- 参见https://docs.joomla.org/Unified_Content_Model。关于UCM(源自eBay)的提案的原始讨论始于2011年12月:https://groups.google.com/g/joomla-dev-platform/c/sqdZ0B_WCiQ?pli=1
- 例如,com_tags组件。它也用于Joomla扩展目录(JED),但结果并不理想。
- 参见例如关于UCM和CCKs的2018年讨论:https://github.com/joomla/joomla-cms/discussions/19150#discussioncomment-221463
- Seblod(使用ACL)的多站功能是这些隐藏宝藏之一。
- 参见https://fabrikar.com/forums/index.php?wiki/list-joins/,https://fabrikar.com/forums/index.php?threads/inverse-databasejoin-element.49424/#post-258361和https://www.youtube.com/watch?v=2JDQChNs50Y(无声音)。
资源
本系列关于构建组件的工具的文章
- 第1集: 介绍和核心解决方案
- 第2集:Joomla中的嵌入式应用程序(本文)
有关模板布局、Hopper包和Seblod包以及我们的活动日程实现的信息,可在本系列存储库中找到。
Seblod
Fabrik
在Joomla社区杂志上发表的一些文章代表了作者在特定主题上的个人观点或经验,可能不符合Joomla项目的官方立场
通过接受,您将访问由https://magazine.joomla.net.cn/之外的第三方提供的服务
评论