A humble PHP framework & CMS
A template is the CMS record that connects a URL to a view file and declares which content blocks are editable on pages that use it. Every page in Humblee is assigned exactly one template.
Templates are managed in Admin > Templates.
Create a PHP file in application/views/. This is the HTML structure of your page. It receives a $content variable — an associative array of content block objects — and uses Draw::content() to output each block in the right place.
<?php
declare(strict_types=1);
use Humblee\Foundation\Draw;
?>
<article class="content">
<h1><?php Draw::content($content, 'page_title') ?></h1>
<div class="intro">
<?php Draw::content($content, 'intro_text') ?>
</div>
<div class="body-copy">
<?php Draw::content($content, 'pagebody') ?>
</div>
</article>
The second argument to Draw::content() is the object key of a block type. It must exactly match the object key of a block that is selected in this template's block list. If the key does not match, the helper outputs nothing silently.
| Helper | Purpose |
|---|---|
Draw::content($content, 'objectkey') |
Outputs the live content for a named block |
Draw::metaTags($content) |
Outputs <title> and <meta> tags from the built-in meta_tags block |
Draw::metaTags() is already called in application/views/templates/template.php for every page, so you do not need to include it in individual view files.
When a user with the content, publish, or admin role views the page, Draw::content() automatically wraps each block in a <div class="cms_block"> with data attributes the CMS toolbar uses to enable inline editing. Your view requires no changes to support this.
Navigate to Admin > Templates and create a new template record. The two most important settings are the page type and the content blocks.
viewUse this for the majority of pages. The CMS renders your view file directly, with the page's content already loaded and passed in as $content.
Set the path field to the path of your view file relative to application/views/, without the .php extension:
about
For a file in a subdirectory like application/views/marketing/landing.php:
marketing/landing
The framework resolves this as application/views/{path}.php.
controllerUse this when the page needs to load its own data before rendering — for example, fetching records from the database, checking a condition, or preparing variables the view depends on.
You provide a controller class name and a method name. The framework instantiates App\Controller\{ClassName} and calls the specified method, passing an array of the current page state ($page, $content, $template). The method returns an HTML string which becomes the rendered page body.
In the CMS, set the controller name and action (method) in the template's path fields.
In code, create application/Controller/YourController.php:
<?php
declare(strict_types=1);
namespace App\Controller;
use Humblee\Foundation\Core;
class YourController
{
public function index(array $templateData): string
{
$content = $templateData['content'];
$page = $templateData['page'];
$items = \ORM::for_table('your_table')->find_many();
return Core::view(
_app_server_path . 'application/views/your-view.php',
['content' => $content, 'page' => $page, 'items' => $items]
);
}
}
The view file receives whatever variables you pass to Core::view(). The $content array is still available for Draw::content() calls — pass it through as shown above.
When to use each: if the page is purely content-driven, use
view. If the page needs to query the database or run application logic before rendering, usecontroller.
The blocks selection on a template determines which block types are editable on pages that use it. This matters for two reasons:
The editor UI. When an admin opens a page's content editor, they see only the blocks listed in the template. If a block is not in the list, there is no way to populate it through the admin interface.
Your view. Draw::content() can only output a block if that block has content saved in the database. A block that was never shown to editors will never have content.
The rule is: every object key you call in your view must have a corresponding block selected in the template. If your view calls Draw::content($content, 'sidebar'), the sidebar block type must be in the template's block list.
For adding multiple instances of the same block type to a single template, see Block slots.