October CMS and Database-driven Components

Illustration of the logo of the October CMS, along with the text "October CMS"

What is October CMS?

A client recently came to us and requested we take over maintenance and enhancements for their website. The site was using a framework I had never heard of before named October CMS. After doing some research I found it was based on Laravel, which in turn is based on Symfony. Since we work with Symfony a lot, I thought it should be fairly easy to get up to speed with this new site.

I found that this is basically a framework designed to hide all the underlying complexity of Laravel and Symfony, so all that knowledge didn’t help in this case. But luckily October CMS is very straightforward, with its target audience being rapid site development.

After working with it for a while and reading through the docs, I found it to be very easy to use. Each page (and URL) is defined in a template file. Each of these files has up to three parts: configuration, PHP, and HTML (using TWIG).

You can hardcode your HTML directly in the page template file, or you can get more flexible and create Components. Components are basically reusable blocks of content you can add to any page, are PHP driven, and use partials to render their content.

Database-driven Components

Components allow passing of variables from the PHP class to the template, so to make Components more flexible you can pass database content through the Component to the template.

This way you can reuse Components on multiple pages, but change the content within for any given page. In this context, you can think of a Component as a section of a page with a specific layout and styling which can have different CMS content rendered in predefined areas.

To accomplish this you can create a table with fields used to store commonly used content types. For this example, we’ll have fields of “title”, “subtitle”, and “content”. This is a simple example, and it’s assumed a rich text editor would be used to set the content.

But depending on your requirements, you can get creative and create child tables to hold repeating content like items in bullet list, FAQ entries, photos for a carousel, etc.

Once you have the table to store the CMS content, you can then use the page configuration to specify which content record should be used for a given page. 

In the example below, we can see for the /example-page it pulls content from the table where id = 1:

url = "/example-page"

[MyComponent] componentContentId = 1

== {% MyComponent %}

Alt text: Code snippet of “/example-page” of content table where id = 1

Now say we have another page. We’ll use the same exact Component but instead populate with content data from the table where id = 2:

url = "/another-page" [MyComponent] componentContentId = 2 == {% MyComponent %}

In the examples above, you can see the Component’s name appears in square brackets. Below the [Component Name] are the Component’s properties, represented as key/value pairs (very similar to an .ini file).

These properties get passed to the Component class when the page is rendered. In the example the table record ID is set as a Component property named componentContentId. Below the “==” is the template section of the page.

You can use HTML here as well as placeholders for where the Component should render. The example currently only renders the Component content. That’s all you need to do to configure a page to use a Component.

Now within the Component class file, here’s how you’d set up the Component to support the ‘componentContentId’ property. All Components must have their properties defined in the defineProperties() method, e.g.:

Class MyComponent extends ComponentBase {     public function defineProperties()     {         $props = [];         $props['componentContentId'] = [             'title' => 'Component Content ID',             'description' => 'component_content record ID ',             'type' => 'string',         ];         return $props;     } ...

The Component class also has a method, onRun(), that runs before the Component renders. This is where you can set the template data. We’ll pull our database content in this method and assign it to the page, example:

... public function onRun() {     $this->page['myComponentData'] = \MyProject\Base\Models\ComponentContent::find($this->property('componentContentId')); } ...

October CMS: Notes and Takeaways

You can see October CMS has an ORM as well, with model classes and all. One thing to note here is that you have to use unique associative keys in $this->page. If you used ‘myComponentData’ in another Component, it would overwrite the data written above.

Then in the template you would use TWIG to access and render the variable data.

Of course to make the system as flexible and useful as possible, you’d have to create backend list and edit views to access and edit the ComponentContent table data, so users can set the CMS content themselves.

Watch for more October CMS articles as we continue to work with the framework.