ThemeService
Registered as service('theme'). Manages theme discovery, activation, and rendering. All public page renders go through this service.
Methods
getActive(): ?object
Returns the currently active theme as an object from the themes table, or null if no theme is active.
$theme = service('theme')->getActive();
// $theme->folder, $theme->name, $theme->version, $theme->status
discover(): void
Scans the themes/ directory for theme_info.json manifests. Inserts new theme records into the themes table. Does not modify existing records. Called from the admin Themes → Discover action.
sync(): void
Reconciles the themes table with the filesystem. Marks themes as unavailable if their directory no longer exists on disk. Called during discover().
view(string $template, array $data = []): string
Renders a .tpl template file within the active theme, merging the provided data with the shared theme data bag.
return service('theme')->view('blog/index.tpl', [
'posts' => $posts,
'pagination' => $pager->links('default', 'bootstrap_full'),
'page_title' => 'Blog',
]);
The $template path is relative to the active theme's views/ directory. view() handles layout inheritance ({% extends %}), merges shared context, and returns the fully rendered HTML string.
Shared Template Data Bag
ThemeService automatically injects these variables into every template render:
| Variable | Source |
|---|---|
site_name | Settings: App.siteName |
site_tagline | Settings: App.siteTagline |
page_title | Passed by controller (defaults to site_name) |
cls | Active theme's css_class_mapping from theme_info.json |
theme_options | Active theme's saved options from theme_options table |
lang_switcher | Available languages from languages table |
current_user | Authenticated user object or null |
auth_groups | Current user's group list |
Usage in Plugin Controllers
Plugin controllers that render public pages must use service('theme')->view() — never CI4's view() helper directly, as CI4's view() does not support absolute paths or the .tpl engine.
// In a plugin public controller
public function index(): string
{
$data = [
'items' => model('MyPlugin\Models\ItemModel')->getAll(),
'page_title' => 'My Plugin',
];
return service('theme')->view('myplugin/index.tpl', $data);
}
Plugin templates must be placed inside the active theme's views directory for view() to find them, or the plugin must ship a fallback template and coordinate with theme developers.