Plugin Structure
A fully-featured plugin uses all of the following directories and files. Only Plugin.php and plugin_info.json are required — everything else is added as your plugin needs it.
Full Directory Tree
plugins/MyPlugin/
├── Plugin.php ← required: implements PluginInterface
├── plugin_info.json ← required: manifest
├── Installer.php ← optional: up()/down() hooks
├── Config/
│ └── Routes.php
├── Controllers/
│ ├── Main.php
│ └── Admin/
│ └── Dashboard.php
├── Models/
│ └── MyPluginModel.php
├── Services/
│ └── MyPluginService.php
├── Database/
│ └── Migrations/
│ └── 2024-01-01-000001_CreateMyPluginTable.php
├── Views/
│ ├── store/ ← public .tpl templates
│ │ └── index.tpl
│ └── admin/ ← admin .php views
│ └── index.php
├── Language/
│ ├── en/MyPlugin.php
│ ├── es/MyPlugin.php
│ ├── fr/MyPlugin.php
│ ├── id/MyPlugin.php
│ ├── pt/MyPlugin.php
│ └── sk/MyPlugin.php
├── Api/
│ └── V1Controller.php
└── assets/
├── css/
└── js/
File-by-File Conventions
Plugin.php
The entry point. Must be in the root of the plugin directory with namespace PluginsMyPlugin. Implements all 7 methods of PluginInterface. Keep this class thin — delegate to services for anything complex.
Installer.php
<?php
namespace PluginsMyPlugin;
class Installer
{
public static function up(): void
{
// Called once on activation (after migrations)
}
public static function down(): void
{
// Called only on explicit uninstall (NOT on deactivation)
}
}
Table Naming
| Plugin | Prefix | Example table |
|---|---|---|
| PvDocs | pvd_ | pvd_articles, pvd_versions |
| DStore | ds_ | ds_products, ds_orders |
| Vetting | vt_ | vt_queue, vt_results |
| MyPlugin | mp_ | mp_items, mp_settings |
Admin Views
return view('Plugins\MyPlugin\Views\admin\index', $data);
Public Views
return $this->themeService->view('Plugins\MyPlugin\Views\store\index', $data);
Language Files
<?php
// Language/en/MyPlugin.php
return [
'page_title' => 'My Plugin',
'no_results' => 'No items found.',
'save_success' => 'Settings saved successfully.',
];
Access via lang('MyPlugin.page_title') in PHP or {! lang "MyPlugin.page_title" !} in templates.
Assets
Static assets that need to be publicly accessible must be placed in public/plugins/{slug}/. The plugin directory itself is not web-accessible.