PluginInterface
Every Plugin.php must implement AppInterfacesPluginInterface. This contract is how Pubvana communicates with your plugin during boot, menu rendering, route loading, and CSRF configuration.
Interface Definition
<?php
// app/Interfaces/PluginInterface.php
namespace AppInterfaces;
interface PluginInterface
{
public function getName(): string;
public function getSlug(): string;
public function getVersion(): string;
public function getMenuItems(): array;
public function getCsrfExemptions(): array;
public function getPublicRoutes(): array;
public function register(): void;
}
Method Reference
getName(): string
Returns the human-readable plugin name. Displayed in the admin panel plugin list.
public function getName(): string
{
return 'Pubvana Docs';
}
getSlug(): string
Returns the plugin's folder name. Used as URL prefix, settings namespace, and DB identifier. Must match the actual folder name under plugins/.
public function getSlug(): string
{
return 'pvdocs';
}
Rules: lowercase, no spaces, no hyphens. Use letters and numbers only.
getVersion(): string
Returns the current version string. Must match the version field in plugin_info.json. Used by the update checker to detect available upgrades.
public function getVersion(): string
{
return '1.1.0';
}
getMenuItems(): array
Returns the admin sidebar menu entry for this plugin. PluginManager merges these into the admin navigation. Return an empty array [] if your plugin has no admin UI.
Return structure:
public function getMenuItems(): array
{
return [
'label' => 'Pubvana Docs',
'icon' => 'fas fa-book',
'children' => [
[
'label' => 'Dashboard',
'url' => '/pvdocs/admin',
'nav_key' => 'pvdocs_dashboard',
],
[
'label' => 'Versions',
'url' => '/pvdocs/admin/versions',
'nav_key' => 'pvdocs_versions',
],
[
'label' => 'Articles',
'url' => '/pvdocs/admin/articles',
'nav_key' => 'pvdocs_articles',
],
],
];
}
Key fields:
label(string) — display text for the menu itemicon(string) — FontAwesome 6 icon class (e.g.,fas fa-book,fas fa-store)children(array) — array of child menu items; each haslabel,url, andnav_keynav_key(string) — unique key used to highlight the active sidebar item; must be globally unique across all plugins
If the plugin has only one admin page and no sub-navigation, use a flat structure (omit children and add url and nav_key directly to the top-level array).
getCsrfExemptions(): array
Returns an array of route patterns that should be exempt from CSRF verification. Used for endpoints that receive external POST requests — webhooks from payment gateways, external APIs calling back, etc.
public function getCsrfExemptions(): array
{
return [
'dstore/webhooks/stripe',
'dstore/webhooks/*',
];
}
Patterns use CI4's route wildcard syntax. These are injected into the CI4 CSRF filter's except list during PluginManager::boot(). Do not use this to exempt your own admin forms — those should use CSRF tokens normally.
Return [] if your plugin has no external webhook endpoints.
getPublicRoutes(): array
Returns an array of public-facing route labels and URLs for this plugin. Used to populate the admin panel's "Public Routes" listing (Appearance or similar admin section). This is informational only — it does not define the actual routes (those go in Config/Routes.php).
public function getPublicRoutes(): array
{
return [
['label' => 'User Docs', 'url' => '/pvdocs/user'],
['label' => 'Dev Docs', 'url' => '/pvdocs/dev'],
];
}
Return [] if your plugin has no public-facing URLs.
register(): void
Called during PluginManager::boot() on every request, after the namespace is registered and before routes are loaded. Use this for:
- Registering CI4 event listeners
- Initialising third-party SDKs that must load early
- Overriding CI4 services for this plugin's scope
- Setting up anything that must happen before controllers run
public function register(): void
{
// Example: register a CI4 event listener
CodeIgniterEventsEvents::on('post_published', function ($post) {
service('mypluginService')->onPostPublished($post);
});
}
For most simple plugins, register() is empty. Do not perform database queries or heavy work here — it runs on every request.
New in 2.3.6— If your plugin implements the Email Provider interface and declares"core"capability, register it here:service('emailProvider')->register($this->getSlug(), new MyEmailProvider());— see Email Provider.
Complete Example (PvDocs Plugin)
<?php
namespace PluginsPvDocs;
use AppInterfacesPluginInterface;
class Plugin implements PluginInterface
{
public function getName(): string { return 'Pubvana Docs'; }
public function getSlug(): string { return 'pvdocs'; }
public function getVersion(): string { return '1.1.0'; }
public function getMenuItems(): array
{
return [
'label' => 'Pubvana Docs',
'icon' => 'fas fa-book',
'children' => [
['label' => 'Dashboard', 'url' => '/pvdocs/admin', 'nav_key' => 'pvdocs_dashboard'],
['label' => 'Versions', 'url' => '/pvdocs/admin/versions', 'nav_key' => 'pvdocs_versions'],
['label' => 'Articles', 'url' => '/pvdocs/admin/articles', 'nav_key' => 'pvdocs_articles'],
],
];
}
public function getPublicRoutes(): array
{
return [
['label' => 'User Docs', 'url' => '/pvdocs/user'],
['label' => 'Dev Docs', 'url' => '/pvdocs/dev'],
];
}
public function getCsrfExemptions(): array { return []; }
public function register(): void { }
}