Plugin Structure

A well-structured plugin follows consistent conventions and organization.

Directory Structure

Complete plugin structure example:

plugins/
└── my-plugin/
    ├── plugin.json                      # Required: Plugin manifest
    ├── Bootstrap.php                    # Optional: Initialization class
    ├── composer.json                    # Optional: Composer dependencies
    ├── Migrations/                      # Database migrations
    │   ├── Version20251214000001.php
    │   └── Version20251214000002.php
    ├── Resources/
    │   ├── config/
    │   │   └── services.yaml           # Service definitions
    │   ├── translations/
    │   │   ├── messages.en.yaml        # English translations
    │   │   └── messages.pl.yaml        # Polish translations
    │   └── views/                       # Optional additional views
    ├── src/
    │   ├── Controller/                  # HTTP controllers
    │   │   ├── HelloController.php
    │   │   └── Admin/                   # EasyAdmin CRUD controllers
    │   │       └── MyCrudController.php
    │   ├── Entity/                      # Doctrine entities
    │   │   └── MyEntity.php
    │   ├── Repository/                  # Doctrine repositories
    │   │   └── MyEntityRepository.php
    │   ├── Service/                     # Business logic
    │   │   └── MyService.php
    │   ├── Widget/                      # Dashboard widgets
    │   │   └── MyWidget.php
    │   ├── EventSubscriber/             # Event listeners
    │   │   └── MenuEventSubscriber.php
    │   ├── Command/                     # Console commands
    │   │   └── MyCommand.php
    │   ├── CronTask/                    # Scheduled tasks
    │   │   └── MyCleanupTask.php
    │   ├── Tab/                         # Server tabs
    │   │   └── MyTab.php
    │   ├── Provider/                    # Payment providers
    │   │   └── MyPaymentProvider.php
    │   ├── Adapter/                     # External API adapters
    │   │   └── ExternalApiAdapter.php
    │   ├── DTO/                        # Data Transfer Objects
    │   │   └── MyDTO.php
    │   └── Exception/                   # Custom exceptions
    │       └── MyPluginException.php
    ├── templates/                       # Twig templates
    │   ├── index.html.twig
    │   ├── widgets/
    │   │   └── my_widget.html.twig
    │   └── tabs/
    │       └── my_tab.html.twig
    ├── translations/                    # Plugin translations (alternative location)
    │   └── plugin_my_plugin.en.yaml
    ├── assets/                          # Frontend assets
    │   ├── css/
    │   │   └── styles.css
    │   ├── js/
    │   │   └── script.js
    │   └── images/
    │       └── logo.svg
    └── tests/                          # Unit and integration tests
        ├── Unit/
        └── Integration/

Required Files

Every plugin must have:

  • plugin.json: Plugin manifest with metadata and configuration

Optional Files

  • Bootstrap.php: Initialization logic when plugin is enabled/disabled

  • composer.json: External package dependencies

  • services.yaml: Service container configuration

File Organization Best Practices

  1. Separate concerns: Controllers, services, entities in separate directories

  2. Follow PSR-4: Namespace must match directory structure

  3. Use consistent naming: Follow Symfony and PteroCA conventions

  4. Group by feature: Related classes in same directory

  5. Keep templates near code: Easy to locate and maintain

PSR-4 Autoloading

Namespace must match directory structure:

Incorrect namespace = "Class not found" errors!

Last updated