CodeIgniter 4 Foundation
Pubvana is built on CodeIgniter 4.7 with Shield 1.3. Understanding the underlying framework is essential for plugin and theme development. This article covers the specific CI4 features Pubvana relies on and how they are used.
CI4 Version and Composer
Pubvana is Composer-managed. The framework lives in vendor/codeigniter4/framework. Never edit framework files directly. Pubvana's composer.json pins CI4 at ^4.7.
composer require codeigniter4/framework:"^4.7"
composer require codeigniter4/shield:"^1.3"
Shield Authentication
Shield provides:
- User model with groups (superadmin, admin, editor, author, subscriber)
- Session-based login with remember-me tokens
- TOTP two-factor authentication (TotpFilter enforces 2FA on admin routes)
- Magic link login (optional)
- Auth filters:
sessionfilter applied globally
Groups are checked via auth()->user()->inGroup('admin') or the has_role() helper defined in app/Helpers/cms_helper.php.
MVC Pattern
Pubvana enforces strict MVC. No business logic in controllers — use Services. No SQL in views. Controllers are thin: validate input, call a service or model, pass data to a view.
Controller → Service → Model → Database
↓
View (theme .tpl or admin .php)
Key CI4 Features Used
Services
CI4's service container (Config/Services.php) provides shared instances. Pubvana registers:
ThemeService— template rendering and theme managementPluginManager— plugin discovery and bootWidgetService— widget rendering pipeline
Access via service('themeService') or dependency injection.
Events
app/Config/Events.php hooks into CI4's event system:
Events::on('pre_system', function () {
// PluginManager::boot() runs here — before routing
service('pluginManager')->boot();
// Locale sync from session
// supportedLocales population
});
The pre_system event fires before routing, which is why plugins can register their own routes.
Filters
Filters in app/Filters/ implement FilterInterface. Registered in app/Config/Filters.php:
| Alias | Class | Purpose |
|---|---|---|
admin_auth | AdminFilter | Requires admin group membership |
totp | TotpFilter | Requires completed 2FA if enabled |
maintenance | MaintenanceFilter | Shows maintenance page to non-admins |
csrf | CI4 built-in | CSRF token validation |
honeypot | CI4 built-in | Bot trap on public forms |
Plugin routes use ['filter' => ['admin_auth', 'totp']] for admin-protected endpoints.
Migrations
Standard CI4 migrations in app/Database/Migrations/. Plugins store their own migrations in plugins/MyPlugin/Database/Migrations/. Run on activation:
$migrate = ConfigServices::migrations();
$migrate->setNamespace('Plugins\MyPlugin')->latest();
Settings Library
The codeigniter4/settings package stores key-value configuration in the settings table. Pubvana uses it for all CMS configuration. Access via setting() helper:
// Read
$siteName = setting('App.siteName');
// Write
setting()->set('App.siteName', 'My Blog');
Cache
CI4's cache driver (file-based by default, Redis-compatible). Used for marketplace API responses, rendered widget output, and plugin-specific caching.
$cache = ConfigServices::cache();
$data = $cache->get('my_key');
$cache->save('my_key', $data, 3600);
Session
CI4's session library. Used for flash messages, locale preference, 2FA state, and Shield's auth session. Access via session() helper.
Validation
app/Config/Validation.php registers custom rule sets. Controllers validate with $this->validate($rules). Plugin controllers follow the same pattern.
Pager
CI4's pager with a custom Bootstrap 5 template registered in app/Config/Pager.php as bootstrap_full. Theme templates receive a $pager object and render it via {! pager !}.
Composer Autoloading
The composer.json autoload section registers App → app/. Plugin namespaces (PluginsMyPlugin) are registered dynamically by PluginManager at runtime using spl_autoload_register — no Composer dump-autoload required for plugins.
app/ Directory Structure
app/
├── Config/
│ ├── App.php # Base URL, indexPage, default locale
│ ├── Auth.php # Shield config, view overrides
│ ├── Constants.php # PLUGINS_PATH, THEMES_PATH, WIDGETS_PATH
│ ├── Events.php # pre_system hook for PluginManager::boot()
│ ├── Filters.php # Filter aliases and global rules
│ ├── Pager.php # bootstrap_full template registration
│ ├── Routes.php # Core routes + plugin route loading
│ └── Services.php # Service registrations
├── Controllers/
│ ├── Admin/ # Admin panel controllers
│ └── *.php # Public controllers (Blog, Page, Search…)
├── Database/
│ └── Migrations/ # Core schema migrations
├── Filters/ # AdminFilter, MaintenanceFilter, TotpFilter
├── Helpers/ # cms_helper.php, theme_helper.php
├── Interfaces/
│ └── PluginInterface.php
├── Language/ # en/, es/, fr/, id/, pt/, sk/
├── Models/ # Core models
├── Services/ # ThemeService, PluginManager, WidgetService…
└── Views/ # Admin PHP views, auth overrides, maintenance.php