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: session filter 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 management
  • PluginManager — plugin discovery and boot
  • WidgetService — 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:

AliasClassPurpose
admin_authAdminFilterRequires admin group membership
totpTotpFilterRequires completed 2FA if enabled
maintenanceMaintenanceFilterShows maintenance page to non-admins
csrfCI4 built-inCSRF token validation
honeypotCI4 built-inBot 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 Appapp/. 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