Plugin Directory Structure β
A detailed explanation of MineAdmin plugin's standard directory structure, file specifications, and organizational approach.
Standard Directory Structure β
A complete MineAdmin plugin directory structure is as follows:
plugin/vendor/plugin-name/ # Plugin root directory
βββ mine.json # Core plugin configuration file β
βββ README.md # Plugin documentation
βββ LICENSE # License file
βββ composer.json # Composer dependency config (optional)
βββ src/ # Backend source directory β
β βββ ConfigProvider.php # Configuration provider β
β βββ InstallScript.php # Installation script β
β βββ UninstallScript.php # Uninstallation script β
β βββ Controller/ # Controller directory
β β βββ AdminController.php # Admin controller
β β βββ ApiController.php # API controller
β βββ Service/ # Service layer directory
β β βββ ExampleService.php # Business service class
β βββ Repository/ # Repository layer directory
β β βββ ExampleRepository.php # Data repository class
β βββ Model/ # Model directory
β β βββ Example.php # Data model
β βββ Request/ # Request validation directory
β β βββ CreateRequest.php # Create request validation
β β βββ UpdateRequest.php # Update request validation
β βββ Resource/ # Resource transformation directory
β β βββ ExampleResource.php # Resource transformation class
β βββ Middleware/ # Middleware directory
β β βββ ExampleMiddleware.php # Custom middleware
β βββ Command/ # Command line directory
β β βββ ExampleCommand.php # Custom command
β βββ Listener/ # Event listener directory
β β βββ ExampleListener.php # Event listener
β βββ Exception/ # Exception handling directory
β βββ ExampleException.php # Custom exception
βββ web/ # Frontend source directory β
β βββ views/ # Page components directory
β β βββ index.vue # Main page
β β βββ list.vue # List page
β β βββ form.vue # Form page
β βββ components/ # Common components directory
β β βββ ExampleComponent.vue # Shared component
β βββ api/ # API interface directory
β β βββ example.js # Interface definition
β βββ router/ # Routing configuration directory
β β βββ index.js # Routing configuration
β βββ store/ # State management directory
β β βββ example.js # State management
β βββ assets/ # Static resources directory
β βββ images/ # Image resources
β βββ styles/ # Style files
βββ Database/ # Database-related directory β
β βββ Migrations/ # Database migration files
β β βββ 2024_01_01_000000_create_example_table.php
β βββ Seeders/ # Data seeder files
β βββ ExampleSeeder.php # Data seeder class
βββ config/ # Configuration file directory
β βββ example.php # Plugin configuration file
βββ publish/ # Publish files directory
β βββ config/ # Configuration file templates
β β βββ example.php # Configuration file template
β βββ assets/ # Static resource templates
βββ tests/ # Test files directory
β βββ Unit/ # Unit tests
β βββ Feature/ # Feature tests
β βββ TestCase.php # Test base class
βββ docs/ # Documentation directory
β βββ installation.md # Installation docs
β βββ usage.md # Usage docs
β βββ api.md # API docs
βββ .gitignore # Git ignore file
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Core File Details β
1. mine.json (Plugin Configuration File) β
File Path: mine.json
(Configuration Details)
Core configuration file defining plugin metadata, dependencies and loading configuration:
{
"name": "vendor/plugin-name",
"description": "Plugin description",
"version": "1.0.0",
"type": "mixed",
"author": [
{
"name": "Author Name",
"email": "author@example.com",
"role": "developer"
}
],
"keywords": ["mineadmin", "plugin"],
"homepage": "https://github.com/vendor/plugin-name",
"license": "MIT",
"require": {
"php": ">=8.1",
"hyperf/framework": "^3.0"
},
"package": {
"dependencies": {
"vue": "^3.0",
"element-plus": "^2.0"
}
},
"composer": {
"require": {
"hyperf/async-queue": "^3.0"
},
"psr-4": {
"Plugin\\Vendor\\PluginName\\": "src"
},
"config": "Plugin\\Vendor\\PluginName\\ConfigProvider"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2. ConfigProvider.php (Configuration Provider) β
File Path: src/ConfigProvider.php
Implementation: Based on Hyperf ConfigProvider mechanism (GitHub)
β οΈ Note: The
publish
feature in ConfigProvider has issues in plugin system, recommend handling config publishing in InstallScript.
<?php
namespace Plugin\Vendor\PluginName;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => [],
'annotations' => [
'scan' => [
'paths' => [__DIR__],
],
],
'commands' => [],
'listeners' => [],
// publish feature not recommended in plugins
// Handle config publishing in InstallScript instead
];
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
3. InstallScript.php (Installation Script) β β
File Path: src/InstallScript.php
Execution Timing: When running mine-extension:install
command Importance: Recommended for handling config publishing, environment checks and database migrations
<?php
namespace Plugin\Vendor\PluginName;
use Hyperf\Contract\ApplicationInterface;
use Hyperf\Database\Commands\Migrations\MigrateCommand;
class InstallScript
{
public function handle(): bool
{
// 1. Environment checks
if (!$this->checkEnvironment()) {
echo "Environment check failed\n";
return false;
}
// 2. Publish config files
$this->publishConfig();
// 3. Run database migrations
$this->runMigrations();
// 4. Initialize data
$this->seedData();
echo "Plugin installed successfully\n";
return true;
}
protected function checkEnvironment(): bool
{
// Check PHP version
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
echo "PHP version needs >= 8.1\n";
return false;
}
// Check required extensions
$requiredExtensions = ['redis', 'pdo', 'json'];
foreach ($requiredExtensions as $ext) {
if (!extension_loaded($ext)) {
echo "Missing PHP extension: {$ext}\n";
return false;
}
}
return true;
}
protected function publishConfig(): void
{
$source = __DIR__ . '/../publish/config/plugin.php';
$target = BASE_PATH . '/config/autoload/plugin.php';
if (!file_exists($target)) {
copy($source, $target);
echo "Config file published: {$target}\n";
}
}
protected function runMigrations(): void
{
$migrationPath = __DIR__ . '/../Database/Migrations';
if (is_dir($migrationPath)) {
// Execute migration command
$container = \Hyperf\Context\ApplicationContext::getContainer();
$application = $container->get(ApplicationInterface::class);
$application->setAutoExit(false);
$input = new \Symfony\Component\Console\Input\ArrayInput([
'command' => 'migrate',
'--path' => $migrationPath,
]);
$output = new \Symfony\Component\Console\Output\BufferedOutput();
$application->run($input, $output);
echo "Database migrations completed\n";
}
}
protected function seedData(): void
{
// Initialize default data
// e.g. create default configs, menus etc.
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
4. UninstallScript.php (Uninstallation Script) β β
File Path: src/UninstallScript.php
Execution Timing: When running mine-extension:uninstall
command Importance: Cleans up config files, database tables and related resources
<?php
namespace Plugin\Vendor\PluginName;
use Hyperf\DbConnection\Db;
class UninstallScript
{
public function handle(): bool
{
// 1. Backup important data (optional)
$this->backupData();
// 2. Drop database tables
$this->dropTables();
// 3. Clean up config files
$this->removeConfig();
// 4. Clear cache
$this->clearCache();
echo "Plugin uninstalled\n";
return true;
}
protected function backupData(): void
{
// Backup important data to specified directory
$backupPath = BASE_PATH . '/runtime/backup/plugin_' . date('YmdHis') . '.sql';
// Implement backup logic
}
protected function dropTables(): void
{
// Drop plugin-created database tables
$tables = ['plugin_example_table', 'plugin_settings'];
foreach ($tables as $table) {
if (Db::schema()->hasTable($table)) {
Db::schema()->drop($table);
echo "Dropped table: {$table}\n";
}
}
}
protected function removeConfig(): void
{
$configFile = BASE_PATH . '/config/autoload/plugin.php';
if (file_exists($configFile)) {
unlink($configFile);
echo "Config file removed: {$configFile}\n";
}
}
protected function clearCache(): void
{
// Clear plugin-related cache
$redis = \Hyperf\Context\ApplicationContext::getContainer()
->get(\Hyperf\Redis\Redis::class);
$redis->del('plugin:cache:*');
echo "Cache cleared\n";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Directory Structure Diagram β
Structure Differences by Plugin Type β
Mixed (Hybrid Plugin) β
Contains complete src/
and web/
directories, providing full frontend+backend functionality.
Backend (Backend Plugin) β
Only contains src/
directory, focused on API services and business logic:
plugin/vendor/backend-plugin/
βββ mine.json
βββ src/
β βββ ConfigProvider.php
β βββ Controller/
β βββ Service/
β βββ Model/
βββ Database/
2
3
4
5
6
7
8
Frontend (Frontend Plugin) β
Only contains web/
directory, focused on UI and interactions:
plugin/vendor/frontend-plugin/
βββ mine.json
βββ web/
β βββ views/
β βββ components/
β βββ assets/
βββ src/
βββ ConfigProvider.php # Minimal config
2
3
4
5
6
7
8
Naming Conventions β
1. Directory Naming β
- Use lowercase with hyphens:
user-management
- Avoid underscores and spaces
2. File Naming β
- PHP class files use PascalCase:
UserController.php
- Vue components use PascalCase:
UserList.vue
- Config files use lowercase:
user.php
3. Namespace Standards β
Follow PSR-4 autoloading:
// Plugin path: plugin/mineadmin/user-manager/
// Namespace: Plugin\MineAdmin\UserManager\
namespace Plugin\MineAdmin\UserManager\Controller;
2
3
File Permissions and Security β
1. File Permissions β
# Set appropriate permissions
find plugin/ -type f -name "*.php" -exec chmod 644 {} \;
find plugin/ -type d -exec chmod 755 {} \;
2
3
2. Security Considerations β
- Use environment variables for sensitive configs
- Avoid hardcoding secrets
- Validate and filter user input
- Use HTTPS for sensitive data
Best Practices β
1. File Organization β
- Organize by feature modules
- Maintain clear structure
- Use meaningful filenames
2. Code Standards β
- Follow PSR-12 coding standard
- Add proper comments
- Use type declarations
3. Version Control β
- Use
.gitignore
for unnecessary files - Create clear commit messages
- Use semantic versioning
Example Project Structure β
View official plugin structures:
App-Store Plugin: MineAdmin official app store plugin demonstrating standard hybrid structure
FAQ β
Q: Where should plugin directories be placed? β
A: Plugins should be placed in project root's plugin/
directory, organized as vendor/plugin-name
.
Q: How to handle plugin dependencies? β
A: Declare dependencies in mine.json
's require
field.
Q: Where do frontend files go after installation? β
A: Files under web/
are copied to frontend project's corresponding locations.
Q: How are database migrations executed? β
A: Call migration logic in InstallScript.php
or use Hyperf's migration commands.