What is a Zero CMS Module?
A Module in Zero CMS is a self-contained, isolated, and decoupled package containing related Models, Controllers, and Views. Modules reside under src/Modules/[ModuleName]/. Toggling a module off at the site level automatically blocks its routes, widgets, and console submenus globally!
Module Directory Structure
Establish your module's folder tree conforming with the following strict naming conventions:
src/Modules/Shop/
├── Controllers/
│ ├── CatalogController.php
│ └── CartController.php
├── Models/
│ ├── Product.php
│ └── Order.php
└── Views/
└── dashboard-widget.php Enforcing Route-Level Module Toggles
To enforce module toggles globally, register your routes inside src/Middleware/Router.php and intercept requests based on active tenant permissions:
// Inside src/Middleware/Router.php
if ($moduleName !== null) {
$site = \Zero\Core\App::getCurrentSite();
if ($site && !$site->isModuleEnabled($moduleName)) {
continue; // Bypasses routing dynamically! (Renders 404)
}
}Decoupled Dashboard Widgets
Modules can register visual workspace cards by defining Views/dashboard-widget.php. It is dynamically loaded if the module is enabled, and integrates with the layout preferences:
<!-- Inside src/Modules/Shop/Views/dashboard-widget.php -->
<?php if (in_array('recent_orders', $enabledWidgets ?? [])): ?>
<div class="dashboard-card">
<h3>Recent Shop Orders</h3>
<!-- Query and loop orders... -->
</div>
<?php endif; ?>Step-by-Step: Initializing and Activating your Module
To instantiate and fully activate your custom module, perform the following 3 steps:
- Write Module Logic: Create your Controller (e.g.
src/Modules/Shop/Controllers/CatalogController.php) extendingZero\Interfaces\Controller. - Register Routes in index.php: Use the
Router::register()helper to map a regular expression path to your namespaced module controller:\Zero\Middleware\Router::register( '#^/shop/catalog$#', \Zero\Modules\Shop\Controllers\CatalogController::class ); - Turn the Module ON: Open your site's seeder JSON (or run a DB query) and insert the module's key (e.g.
"shop") into theenabled_modulesJSON column of thesitesdatabase table:"enabled_modules": ["shop"]