Plugins
ZAPHYR is a modular and extensible PHP framework designed with flexibility and developer productivity in mind. Its architecture is built around a powerful plugin system that allows you to enhance and customize the framework's core functionality with ease.
Plugins in ZAPHYR can seamlessly integrate additional features such as services, CLI commands, controllers, middleware, and event listeners. This enables you to tailor the behavior of your application without modifying the core framework.
A growing ecosystem of official plugins is already available, offering ready-to-use solutions. However, ZAPHYR also empowers developers to build their own custom plugins to address specific project requirements, promoting clean separation of concerns and maintainable codebases.
Whether you're building small microservices or large-scale enterprise applications, ZAPHYR's plugin-based architecture ensures that your code remains modular, reusable, and easy to extend.
Plugin installer
ZAPHYR includes a powerful plugin installer system that simplifies the process of integrating and managing plugins
within your application. This system is enabled through the allow-plugins
section in your app’s composer.json
file:
"allow-plugins": {
"zaphyr-org/plugin-installer": true
}
This configuration enables Composer to execute the ZAPHYR plugin installer during dependency installation or updates.
The plugin installer automates the integration process for any plugins defined in your composer.json. When you run
composer install
or composer update
, it will:
- Detect any registered ZAPHYR plugins
- Copy necessary configuration files
- Set up environment variables
- Autoload and register: service providers, console commands, controllers, middleware, and event listeners
This ensures a seamless and consistent setup of third-party plugins without requiring manual configuration.
For plugin authors, this system also allows defining integration logic directly in the plugin's composer.json
,
enabling ZAPHYR to manage everything automatically.
Create custom plugins
Creating your own plugin for ZAPHYR allows you to encapsulate and distribute reusable functionality across projects or teams. The process is straightforward and follows a structured approach to ensure seamless integration with the framework.
To build a custom plugin, you typically follow two main steps:
- Set up the plugin package
- Define plugin metadata and integration logic
Let's walk through the process of creating a custom plugin step by step.
Plugin composer.json
To create a custom plugin, you must define its metadata and behavior in a composer.json
file. This file is essential
for ZAPHYR to recognize, install, and manage your plugin correctly.
The key elements of the composer.json file include:
type
: Must be set tozaphyr-plugin
so ZAPHYR treats the package as a plugin.extra.zaphyr.plugin-classes
: Specifies the classes the plugin installer should register, and the environments in which they should be active (e.g.,all
,development
,production
).
{
"name": "acme/my-plugin",
"type": "zaphyr-plugin",
"autoload": {
"psr-4": {
"Acme\\MyPlugin\\": "src/"
}
},
"extra": {
"zaphyr": {
"plugin-classes": {
"Acme\\MyPlugin\\MyPlugin": [
"all"
]
}
}
}
}
Plugin environments
In the extra
section of your plugin's `composer.json, you can define which environments the plugin class should be
loaded in. This gives you fine-grained control over when your plugin is active, depending on the application's runtime
environment.
You can specify one or more of the following values:
Field | Description |
---|---|
all |
Load the plugin class in all environments. |
development |
Load only in the development environment (e.g., during local development). |
testing |
Load only in the testing environment (e.g., for automated test runs). |
production |
Load only in the production environment (e.g., live/production deployments). |
This mechanism ensures that plugins behave appropriately in different stages of the application lifecycle.
Copy files
You can specify files or directories that should be automatically copied to specific locations within your application when the plugin is installed. This is useful for distributing configuration files, assets, or other resources required for your plugin to function correctly.
To define copy operations, add a copy
section under the extra.zaphyr
key in your plugin’s composer.json
file:
{
"name": "acme/my-plugin",
"type": "zaphyr-plugin",
"autoload": {
"psr-4": {
"Acme\\MyPlugin\\": "src/"
}
},
"extra": {
"zaphyr": {
"plugin-classes": {
"Acme\\MyPlugin\\MyPlugin": [
"all"
]
},
+ "copy": {
+ "config/plugins/my-plugin.yaml": "%config%/plugins/my-plugin.yaml",
+ }
}
}
}
In the copy section:
- The left-hand side defines the source file or directory within your plugin.
- The right-hand side defines the destination path in the host application.
ZAPHYR supports a set of placeholders in destination paths that will automatically resolve to the appropriate application directories:
Path | Description |
---|---|
%root%/ |
Root directory of the application. |
%app%/ |
Application directory (typically where app logic resides). |
%bin%/ |
Directory for CLI scripts (e.g., bin/zaphyr ). |
%config%/ |
Configuration directory, typically where .yaml or .php config files are placed. |
%public%/ |
Public directory, used for web-accessible resources. |
%resources%/ |
Resource directory, ideal for views, language files, or static assets. |
%storage%/ |
Storage directory, used for cache, logs, or other writable data. |
Always use the ZAPHYR-provided placeholders instead of hardcoded paths. This ensures your plugin remains compatible with projects that use a custom directory structure.
Add environment variables
If your plugin relies on specific environment variables, you can define them under the env
section in your plugin’s
composer.json
file. This allows you to set default values that will be added to the application’s .env
file during
installation.
{
"name": "acme/my-plugin",
"type": "zaphyr-plugin",
"autoload": {
"psr-4": {
"Acme\\MyPlugin\\": "src/"
}
},
"extra": {
"zaphyr": {
"plugin-classes": {
"Acme\\MyPlugin\\MyPlugin": [
"all"
]
},
"copy": {
"config/": "%config%"
},
+ "env": {
+ "ACME_MY_PLUGIN_SETTING": "default_value"
+ }
}
}
}
These environment variables will be appended to the .env
file of the application in the following format:
### start-plugin-config:acme/my-plugin ###
ACME_MY_PLUGIN_SETTING=default_value
### end-plugin-config:acme/my-plugin ###
The block is clearly marked using start-plugin-config
and end-plugin-config
comments. These markers are essential,
they allow the plugin installer to manage the configuration block reliably during updates or removals. You should
not modify or remove these comments manually.
Naming environment variables
When defining environment variables for your plugin, it's crucial to follow a consistent naming convention to ensure
to avoid conflicts with other plugins or core application variables; environment variable names should be prefixed
with the plugin’s namespace, typically the uppercased vendor and plugin name. For example, for a plugin named
acme/my-plugin
, use variables like:
ACME_MY_PLUGIN_*
This ensures your variables remain uniquely scoped to your plugin and follow best practices for modular configuration.
Plugin class
The core of any ZAPHYR plugin is its plugin class. This class acts as the entry point for your plugin and defines the components it contributes to the application, such as service providers, console commands, controllers, middleware, and event listeners.
To create one, extend the Zaphyr\Framework\Plugins\AbstractPlugin
class. Your plugin class should implement one or
more static methods to return arrays of the components it registers.
Below is a sample plugin class that includes all available component types:
<?php
declare(strict_types=1);
namespace Acme\MyPlugin;
use Acme\MyPlugin\Commands\MyPluginCommand;
use Acme\MyPlugin\Controllers\MyPluginController;
use Acme\MyPlugin\Listener\MyPluginListener;
use Acme\MyPlugin\Middleware\MyPluginMiddleware;
use Acme\MyPlugin\Providers\MyPluginServiceProvider;
use Zaphyr\Framework\Events\Http\RequestStartingEvent;
use Zaphyr\Framework\Plugins\AbstractPlugin;
class MyPlugin extends AbstractPlugin
{
/**
* Register service providers used by this plugin.
*
* {@inheritdoc}
*/
public static function providers(): array
{
return [
MyPluginServiceProvider::class,
];
}
/**
* Register CLI commands provided by this plugin.
*
* {@inheritdoc}
*/
public static function commands(): array
{
return [
MyPluginCommand::class,
];
}
/**
* Register controllers used by this plugin.
*
* {@inheritdoc}
*/
public static function controllers(): array
{
return [
MyPluginController::class,
];
}
/**
* Register HTTP global middleware provided by this plugin.
*
* {@inheritdoc}
*/
public static function middleware(): array
{
return [
MyPluginMiddleware::class,
];
}
/**
* Register event listeners for the application.
*
* {@inheritdoc}
*/
public static function events(): array
{
return [
RequestStartingEvent::class => [
MyPluginListener::class,
// Listener with optional priority
[
'listener' => MyPluginListener::class,
'priority' => 100,
]
],
];
}
}
You only need to define the methods relevant to your plugin. If your plugin does not provide, for example, middleware or commands, you can omit those respective methods entirely.
This modular approach keeps your plugin class clean and focused, allowing it to scale gracefully as your plugin grows.
Register the plugin
After you've created your plugin class and defined its metadata in the plugin’s composer.json
file, the final step is
to register it in your application so that it can be installed and used.
Add the plugin to your application
Include your plugin in the require
section of your application's root composer.json
file:
{
"require": {
"acme/my-plugin": "^1.0"
}
}
If you're developing the plugin locally, make sure you also define a local path repository using the repositories
key so Composer knows where to find it.
After adding the plugin to your composer.json
, you can run the following command to install it:
Install the plugin
Once the dependency is added, install it via Composer:
composer install
This command triggers ZAPHYR’s plugin installer, which will:
- Parse your plugin’s
composer.json
- Copy files and configuration assets (as defined under
extra.zaphyr.copy
) - Set environment variables (defined in
extra.zaphyr.env
) - Automatically register your plugin’s classes, such as service providers, commands, middleware, controllers, and event listeners
After installation is complete, your plugin is fully integrated into the application and ready to use. All declared components will be autoloaded and registered by the framework automatically, so you can start leveraging your plugin’s functionality right away.