Mecha CMS

Updates.

The Principle of Emptiness

It is the developer’s right to improve the CMS feature.

I really need to update the documentation about future layout API, but to give a general picture for beginners, I decided to publish this article. I guess you never know that you can make parts of the layout to be specifically loaded only on certain pages. That’s reasonable, because until now I still don’t have the opportunity to document it.

The most basic specification of the layout files loading system is dependent on page.php and pages.php files only. We, in fact don’t even need the index.php file. The index.php file is basically just a free space to make it easier for developers to add layout features without having to touch the core CMS feature. Because in principle, our web pages only consist of two forms: item and items. And here, we call item as page and items as pages.

The following is the most minimal layout file structure you can make:

.\
└── lot\
    └── layout\
        ├── page.php
        └── pages.php

Yep. That is all. The before.php, after.php and nav.php files, for example, they are actually just additional files that are not mandatory and are only made to help us reduce in writing the same code over and over again. We usually use before.php file to display the top of the page that doesn’t change everywhere such as page header and page navigation, and then we will use after.php file to display the bottom of the page that doesn’t change like footnotes and copyright statements:

.\
└── lot\
    └── layout\
        ├── after.php
        ├── before.php
        ├── page.php
        └── pages.php

Inside page.php and/or pages.php files, we include those parts like this:

<?= Layout::get('before'); ?>
<!-- Your content goes here -->
<?= Layout::get('after'); ?>

Good news for future Mecha CMS users! Because you can call layout parts in a neater way. As layout files are called inside a class method, then we can actually call other parts of it using the generic self and static keyword. Just think of that files as part of the class method:

<?= self::get('before'); ?>
<!-- Your content goes here -->
<?= self::get('after'); ?>

But wait! We can even simplify it like this:

<?= self::before(); ?>
<!-- Your content goes here -->
<?= self::after(); ?>

Mecha uses PHP’s __callStatic magic method to add that default behavior, that is, to load before.php and after.php files if exists, as long as you haven’t created custom methods named before and after through the Genome class feature.

That means you can call any method through it without having to worry about error messages that will appear as when you declare a function that never existed. That’s the reason I prefer classes with a bunch of static methods rather than static functions like layout_before() and layout_after(). Mecha will try to find foo.php file when you declare self::foo(), and if the file does not exist, nothing will be returned. As simple as creating a widget.php file, we have added widget method to the system automatically!

<?= self::widget(); ?>

The next advantage is the namespace. self::before() and self::get('before') will try to load before.php file, but with namespace defined in the first argument, we can load other files located in the before folder. For example, if we declare self::before('art') or self::get('before/art'), then we will get .\lot\layout\before\art.php loaded into the page if we have it, otherwise, it will load the before.php file, otherwise, it will return nothing:

<?= self::before('art'); ?>
<!-- Your content goes here -->
<?= self::after(); ?>
.\
└── lot\
    └── layout\
        ├── before\
        │   └── art.php
        ├── after.php
        ├── before.php
        ├── page.php
        └── pages.php

These capabilities are unlimited, and the system will prioritize the longest namespace to load. With page extension, this feature is also available automatically for the current page based on the URL path. For example, we can create a special home page layout by creating an index.php file in the page folder (because the default home page layout is constructed via index.page file). Or, we can also create special articles layout by creating article.php file in the pages folder:

.\
└── lot\
    └── layout\
        ├── before\
        │   └── art.php
        ├── page\
        │   └── index.php
        ├── pages\
        │   └── article.php
        ├── after.php
        ├── before.php
        ├── page.php
        └── pages.php

The next advantage is the Genome feature itself. We can change the way self::before() works simply by creating a new method called before to the Layout class:

Layout::_('before', function(array $lot = []) {
    return 'Custom layout start!';
});

We can also add certain features that you can use in the layout with this capability. In index.php file, we add this declaration:

Layout::_('hasExtension', function(string $name) {
    return null !== State::get('x.' . $name);
});

And in the layout file, we could call it this way:

<?php if (self::hasExtension('comment')): ?>
<?= self::comments(); ?>
<?php endif; ?>