17 minutes reading time (3455 words)

Tools to build a Component - 2: An Embedded Application

Building-Components-P2

In the second episode of our building-tools adventure we'll delve deeper into our event schedule example and explore how to implement it using two Joomla application builders — Seblod and Fabrik. We'll not yet create a full component, instead we’ll embed our application within these extensions. By doing so we will also get a better understanding of the requirements for the component we want to build in subsequent articles of the series.

Our journey until now

In episode one we introduced an event schedule, like the schedule for the JoomlaDagen, as an example. We demonstrated how to build a basic event schedule application without creating a custom component, using Joomla’s core features. We used additional fields (1) to enhance core content types like articles and categories.

We analysed our event schedule example by designating entities and their relations.

I used some of the data from the original JoomlaDays 2024 schedule and in our implementation with additional fields the schedule looked like this:

Event Schedule output episode 1
 

My overview of the speakers looked like this:

Speakers overview output episode 1 

Details of the template layouts can be found in the repository for this series.

Value Object

In our event schedule example we have the following concepts: 

  • A page with a schedule/program: a Container.
  • One or more “tracks” to schedule events: a Section (multiple sections can schedule events simultaneously, at the same time).
  • Something that happens, for instance a presentation: an Event.
  • An object, which defines where and when an event takes place: a Locator.
  • The one who does the event, for instance a speaker or a band: an Actor

We called all those basic building blocks “entities”. But in our implementation with additional fields in fact we only created Event and Actor as entities, with their own id.


Entities are objects characterised by a distinct identity. Even when their attributes change, they are still the same entity. They are usually represented by a unique identifier. Value objects  (2), on the other hand, do not have a distinct identity. They are defined solely by their values. If two value objects have the same values, they are considered equal.

The locator object is just a bunch of values; a value-object, not an entity. An event-entity can contain zero or more locator-objects, defining where and when an event takes place. In episode one the container and section were implemented as a fixed set of values (“enum”); these values were set as the options of a select-field.

Here is an Entity Relationship Diagram (ERD) of our example with two entities, as we factually implemented it in episode one:

ERD with event and actor entities


Locator-objects are part of an event-entity. The diagram shows this with the diamond at one end of the connection line. The “0..n” mark means that an event can contain zero or more locators. This was implemented in episode one with a non-required, multiple subform-field.

More Entities

We want to be able to manage the possible values for containers and  sections in a standard content management way: adding, editing and deleting them in their own table. Hence we’ll make them separate content types, separate entities again. We also want to add the information in which container which sections can be used.

In episode one for convenience we used tags to indicate the type of events. Tags were already available as a field in the base article content-type. A disadvantage was that we had to define those tags in another place (the Tags component), while using them only within our application. It is a good principle in software design to put together what belongs together. That’s why we will make a separate entity for event types. An event can only have one event type.

Our Entity Relationship Diagram (ERD) now looks like this:

ERD with 5 entities

Many to Many

In our model, actors and events have a “many-to-many” relationship, meaning that an event can be done by multiple actors and an actor can do multiple events. In episode  one we implemented both the actors field (in the event-entity) as the events field (in the actor-entity) as a multiple select from all possible actors or events. But there was no real connection between those two selections: if you add an event to an actor, then that actor is not automatically selected in the actors field of that event. You’ll have to define those connections on two sides. The information is “redundant” and might be inconsistent.

In a normalised (3) relational database a many-to-many relationship is implemented with an extra “junction” table. That junction table combines a key from the event table with a key from the actors table. 

In Seblod I implemented that relation like in the last episode: adding the relation on both sides. In Fabrik I implemented it with a junction table, as we will also do in the next episode, when we finally create a “real” component.


General variables

In episode one we created some general variables for our event schedule as additional fields for the Event Schedule category. When we build a component, we can build those variables as parameters of the component. For now we will put them in an extra table.

Content Construction and Application Builder

Fabrik is a Joomla component to build custom applications. It has been around for quite some time: Fabrik 1.0 came out in 2007, for Joomla 1.0 (4). It focuses on building applications for Joomla’s frontend, defining forms, fields (“elements”), lists and layouts (“visualizations”). Fabrik automatically creates custom, normalised tables for the application content.

When Drupal 5.0 was released in 2007, it introduced  a “Content Construction Kit” (CCK), a tool that empowered users to create custom content types directly from the backend. Joomla's approach at the time focussed on custom component development for new content types. From about 2009 several CCKs were built for Joomla, like FlexiContent,  K2, Zoo, Seblod, Cobalt and TF Content. After the hype between 2010 and 2013 interest in Joomla’s CCKs declined, as you can see on Google Trends (5):

Google Trends CCKs in Joomla


In Joomla 3.1 (April 2013) a beginning of a core solution for different content types was added: Unified Content Model (UCM) (6). It was used in some core features (7) , but never was a real success. In Joomla 4 (8) it was dropped, but still some reminiscences of it are left. Since Joomla version 3.7 (2017) additional fields were integrated in core, which provided much of the functionality for which CCKs were needed.

Besides Fabrik we will only look at one other CCK / Application Builder in this episode: Seblod. The choice to pick Seblod of all possible CCKs is rather random. Implementing our event schedule in another CCK might have given some other nice results. My intention is not to be complete, but to show how an application built with a CCK is somewhere in between a core implementation and a component.


The road we walk in the first two episodes of this series:

  • Episode 1: extend existing article and category tables with additional fields, expanding existing core content types.
  • Episode 2: use an application builder to add new content types. The application runs “under” the application builder, is “embedded” in Seblod or Fabrik.

Application embedded in Seblod or Fabrik


We can only scratch the surface of Seblod and Fabrik in this article. We’ll show some possibilities to implement our event schedule example without building a component, more advanced than with just core features. Fabrik, Seblod and other Content Construction Kits deserve their own article in this magazine to fully show their capabilities (9)


Seblod

Documentation: https://www.seblod.com/resources/manuals.
Dark mode made the headings of tabs less readable, hence the screenshots in light mode.

Steps I took to implement our event schedule example in Seblod:

  1. Create an app-folder.
  2. Create content types and forms.
  3. Create a repeating group for the locator.
  4. Add links to other content types.
  5. Create lists.
  6. Create a template for the schedule.

1 - Create an app-folder

Navigate to Seblod Core > App Folders, and create an app folder “Event Schedule” under Top > SEBLOD > Apps with the button “+ New”.

Seblod App folder


2 - Create content types and forms

Navigate to Seblod Core > Forms & Content Types, and set the dropdown labelled 'Any App Folder' to 'Event Schedule'. Create new content types for our entities (container, section, event, event_type and actor). Set “App Folder” to  “Event Schedule” in every entity. 

In Seblod it is common to set “Content Object” to “Article”. In that way our starting point would be articles in com_content, just like we did in episode one. All extra fields that cannot be mapped to fields in the article content-type will then be stored in an extra table (#__cck_store_form_<name of content-type>).

Because in our next episode we are going to make a component with its own tables, I now in Seblod have also put all the fields in their own tables. I kept that name Seblod would make for a table (#__cck_store_form_<name of content-type>), but I could have taken other table names. I made the tables in PhpMyAdmin and gave them an id-field with autoincrement:

tables for Seblod in PhpMyAdmin

Seblod-add id-field to table 

Don’t be put off by this if you have never done this: normally in Seblod it is much easier when you just work with Joomla articles as basic content object. But if you want to learn to make your own components, then it is a good time-investment to play with databases and PhpMyAdmin.

When working with our own tables, not using the #__content table, we put  “Content Object” to “Free”.

Create fields for the entities, for instance “container_name” for the container by using the + button on the right panel:

Seblod=section content type

By default all created fields are put in the “Admin Form” template, but you can easily put them in a frontend form by clicking on the “Site Form” button. Then you can drag & drop the fields into it. Such a frontend form can for instance be used for a business directory or a survey form. When using a frontend form, don’t forget to add a submit-button.

In the Type-dropdown you can choose what type of field you want to create. Some common are (just like elsewhere in Joomla):

  • Text: a simple text input field
  • Wysiwyg Editor: a multiline field with an editor
  • Select Numeric

Seblod has a nice image upload field that automatically makes thumbnails. There are more field types in the Seblod Store.

3 - Create a repeating group for the locator

The locator is a set of values in an event that can be repeated. This can be implemented with a GroupX-field.

Seblod - Content types

4 - Add links to other content types

Use a “Select Dynamic” field to make a dropdown with a connection to another related entity. For instance for the event type an event belongs to. Can also be multi-select, for instance to select the containers a section belongs to: Seblod - Containers field

In the Seblod Store there is a cascading dynamic select field available (€ 20), that is dynamically filled using Ajax.

5 - Create lists

Navigate to Seblod Core > List & Search Types, and create lists of all the entities. Those lists will also appear under the Seblod Apps Administrator Menu-item, so you can edit the data in the backend.

6 - Create a template for the schedule

You can use “drag & drop templating” to put all variables in a template. I had to make a new Seblod list-template to show our event schedule. I made it based on the blog-layout override we made in episode one. Those templates are installed via the Joomla installer just like any other Joomla template. My custom template and more details can be found in the repository of this series. After installing, navigate to Seblod Core > Templates to use the template as a list-template. The list-templates can be shown on the website by creating a menu-item for it.

Export

A Seblod application can be easily exported (and imported to another site with Seblod). Navigate to Seblod Core > App Folders, and click on the 3 dots at the line with the ”Event Schedule” application; you’ll see a “Download this App” link:

Download a Seblod application

You’ll get an  app_cck_event_schedule.zip export package, which can be simply installed with the Joomla Extension Manager (on a site that has Seblod installed). You can also export menu-items in the package. If you also want to export the data from your application, there is a SEBLOD Exporter add-on available (€ 20).  In the Seblod Store there are also some complete packages.



Fabrik

Documentation: https://fabrikar.com/forums/index.php?wiki/

Steps I took to implement our event schedule example in Fabrik:

  1. Create Forms for the entities.
  2. Create a Group for the locator-object.
  3. Create Elements for all groups.
  4. Create the many-to-one relations.
  5. Create the many-to-many relations.
  6. Create menu-items for the lists.
  7. Create a “visualization” of the data.


1 - Create Forms

Create forms for all entities and the general parameters. Put a prefix in front of the table name (I used “afab_eventschedule_”), otherwise you’ll just get tables “container, “section” etc.

Fabrik - table prefix

Let Fabrik automatically create a group with the same name.

2 - Create an extra Group

Create a group for the locator-object. Add that group to the event-form. Then go back to the locator-group and make it repeatable.


3 - Create Elements for all groups

Fabrik refers to fields as 'elements'. Create elements for all groups. An id was already automatically created for all entity-tables. Also a date-time for when the last modification was, but you can delete that if you’re not interested in that. All elements will be automatically added to the tables in the database.


4 - Create the many-to-one relations

In the locator-object we choose a container and a section and in the event-entity we choose an event type. Those are all implemented as a dropdown select via a “databasejoin”-field. Simply make a new field (container, section and event_type) in the respective groups, field-type (= plug-in): = databasejoin and get get the id and name from the joined table:

Fabrik - databasejoin-field

5a - Many-to-many relation one sided

When you only want to use a many-to-many relation from one side, you can use a databasejoin-field, just like we did with a many-to-one relation. For instance in our section we show a field to select multiple containers we can use that section in, but in our container we don’t use such a field to show all sections that can be used in that container. The only difference now is that we use a multi-select dropdown to select our containers:

Fabrik - many-to-many one-sided


In the background Fabrik also makes a junction table in that case, the “section_repeat_containers” table:

Database tables Fabrik


In our JoomlaDagen example all rooms (sections) were available on both days (containers). But that is not necessarily the case in other schedules. To correctly implement that, we’d better make those two dropdowns in the locator for container and section cascading, so when choosing a container in the first dropdown, we only see the sections that are available for that container in the second dropdown. Fabrik has cascading dropdown fields for that.

5b - Many-to-many relation two sided

But now we want to add an events-field to the actor entity to select the events that actor does and an actor-field to an event-entity to select all actors who do this event. So: a real two-sided many-to-many relation. That needs several steps :

  • Create the actors-events junction-table. In Fabrik you do this by creating an actors-events-form and have that automatically create a group with the same name, a list and a table (only add the “afab_eventschedule_” prefix).

  • Create elements (= fields) actor_id and event_id in that actors-events group.

  • Create two list joins: in the events list, create a join from event.id to actors-events.event_id, and in the actors list as actor.id to actors-events.actor_id. In both cases, set the join to Repeat.

  • You’ll get two repeat-groups, that I renamed to Actor_Events (for the events in an actor entity) and Event_Actors (for the actors in an event-entity):

Fabrik - repeat groups


In those repeat-groups you’ll find records of our junction-table: pairs of actor_id and event_id. In an actor-entity we are not interested in the actor_id of this record, so we hide that one:

Fabrik - Hidden join field

And the same for the event_id in the Event_Actors group.

  • Finally we would like to see the names of the selected events and actors, not their id. We know that trick: we change the field-type of that event_id and actor_id in their name by respectively joining with the events-table and with the actors table using a databasejoin-field. Here is a screenshot for our event_id in our Actor_Events repeat group:

show event_name on event_id

In essence those steps boil down to:

  • Get the ids of the related entities from the junction table.
  • Resolve those ids to the related entities (or a property, like their name).

Next episode we will do this too in our component.

6 - Create menu-items

Adding content in the backend is possible with Fabrik, but it is more aimed at using our lists and forms in the frontend. Create menu-items for the lists, restricting use to Super Users (or a special group). So you have to be logged in in the frontend in order to add content.

 

7 - Create a “visualization” of the data

We’ll have to make a time-table for our schedule, using the ingredients we’ve put in our content types.

 

Export

Since version 4 there is no export for a Fabrik application “package” anymore.



Schedule output

The output from the three methods we used in the first two episodes (core additional fields, Seblod and Fabrik) is the same, as we basically used the same template layouts for the schedule. We will also get the same output when we make a Joomla component in the next episode.


Takeaways

Some aspects we showed in the first two episodes:

  • Analysis of the data into entities and value objects.
  • Relations between entities and the need for a junction table when using a two-sided many-to-many relation in a normalised relational database.
  • You can accomplish the same results by sticking to a completely normalised database, like Fabrik does, or by putting multiple values in a field, like core additional fields and Seblod do. Both have advantages and disadvantages. In our own component we’ll come back to this design decision.


Left out

What we left out until now, but would make our application more mature:

  • Validation and restriction of input. A “business rule” for our application is: there should be no overlap of events within one section (track) of a schedule. And also: an actor cannot be simultaneously in two places at the same time.
  • The process of scheduling. We now fill in locator-objects for each event, but we better have some overview of what events are still not scheduled and put them in the schedule, preferably with drag and drop. And then also: automatically calculate endtime from starttime + duration.
  • Testing of our application. Does it work correctly, also in edge cases?

Next month: a real component!

Buckle up, for next month we will finally build a Joomla component for our event schedule example. We’ll show how to make your own component and explain some basic patterns like model-view-controller and dependency injection. We’ll also show some more advanced features such as implementing non-redundant many-to-many relationships. Stay tuned to put your Joomla development skills in the next gear!


Notes

  1. In episode one an explanation was given why I use the term “additional fields” instead of  “custom fields”.
  2. Term from “Domain Driven Design”, Eric Evans 2004
     Book cover Domain Driven Design
  3. A field in a normalised relational database only contains a single value and no information is stored double (“redundant”). See a.o. https://en.wikipedia.org/wiki/Database_normalization and https://www.databasestar.com/database-normalization/
  4. See manual for Fabrik 1.0 and interview with Rob Clayburn, both from 2007.
  5. Also interest in Fabrik declined, as you can see in this comparison of Fabrik with FlexiContent on Google Trends: 
     Joomla-Fabrik-FlexiContent Trend
  6. See https://docs.joomla.org/Unified_Content_Model. Original discussion from December 2011 about the proposal for UCM (that originated from eBay): https://groups.google.com/g/joomla-dev-platform/c/sqdZ0B_WCiQ?pli=1
  7. For instance for com_tags. It has also been used for the Joomla Extensions Directory (JED), but not with positive results.
  8. See a.o. this 2018 discussion about UCM and CCKs: https://github.com/joomla/joomla-cms/discussions/19150#discussioncomment-221463
  9. An example of one of those hidden gems is the multi-site feature of Seblod (using ACL).
  10. See https://fabrikar.com/forums/index.php?wiki/list-joins/, https://fabrikar.com/forums/index.php?threads/inverse-databasejoin-element.49424/#post-258361 and https://www.youtube.com/watch?v=2JDQChNs50Y (no sound).

 

Resources

Articles in this series about Tools to build a Component:

Extra material like template layouts, Hopper package and Seblod package with implementation of our event schedule can be found in the repository for this series.


Seblod

Fabrik

 

 

 

Some articles published on the Joomla Community Magazine represent the personal opinion or experience of the Author on the specific topic and might not be aligned to the official position of the Joomla Project

1
How to create a full screen photograph home page
Yannick Gaultier, the man behind Weeblr
 

Comments

Already Registered? Login Here
No comments made yet. Be the first to submit a comment

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/