Creating a Module
1. Implement Required Interfaces
In your plugin class, implement IModule and any scope interface you need:
| Scope | Interface | Lifecycle Method |
|---|---|---|
| System | ISystemSpaceModule |
onLoadSystemSpaceModule() |
| Workspace | IWorkSpaceModule |
onLoadWorkSpaceModule() |
| User | IUserSpaceModule |
onLoadUserSpaceModule() |
These lifecycle methods replace onInit() for module-specific initialization. Keep onInit() only for logic that must run unconditionally (e.g. facade setup).
2. SQL Migration
Register the module in the modules table. The plugin column holds the class name without the Plugin suffix.
MySQL
INSERT INTO `modules` (`caption`, `ident`, `plugin`, `required`, `description`, `hooks`, `is_active`, `is_workspace`)
VALUES ('Test Module', 'test_module', 'TestModule', NULL, 'Test description.', NULL, 1, 1);
Postgres
INSERT INTO modules (caption, ident, plugin, required, description, hooks, is_active, is_workspace)
VALUES ('Test Module', 'test_module', 'TestModule', NULL, 'Test description.', NULL, true, true);
Set is_workspace = true/1 for workspace-scoped modules.
3. Add a Menu Item (optional)
Implement IModuleMenuFetcher and add the item inside onFetchModuleMenuHandler. Gate it behind a permission check.
use DisplayPlugin;
use plugin\Modules\IModule;
use plugin\Modules\domain\listener\IModuleMenuFetcher;
use plugin\Modules\domain\model\MenuItemValuesObject;
class TestModulePlugin extends DisplayPlugin implements IModule, IModuleMenuFetcher
{
/**
* @event IModuleMenuListener
* @param array $menuItems
* @param string|null $area
*/
public function onFetchModuleMenuHandler(array &$menuItems, ?string $area): void
{
if (!$this->hasUserPermissionToSection('some_section')) {
return;
}
$menuIdents = array_column($menuItems, MenuItemValuesObject::FIELD_IDENT);
$idParentMenuItem = array_search('parent', $menuIdents);
if (!$idParentMenuItem || empty($menuItems[$idParentMenuItem])) {
return;
}
if (empty($menuItems[$idParentMenuItem][MenuItemValuesObject::FIELD_ITEMS])) {
$menuItems[$idParentMenuItem][MenuItemValuesObject::FIELD_ITEMS] = [];
}
$menuItems[$idParentMenuItem][MenuItemValuesObject::FIELD_ITEMS][] = [
MenuItemValuesObject::FIELD_CAPTION => __('Menu item 1'),
MenuItemValuesObject::FIELD_URL => $this->getUrl('/test/module/menu/'),
MenuItemValuesObject::FIELD_IDENT => 'menu-item-1',
];
}
}