A lightweight, modern dependency injection framework for WordPress plugins and themes. Built with PHP 8.1+, it provides a robust DI container and abstract application layer to help you write cleaner, more maintainable WordPress code.
- Modern Dependency Injection Container: Manage your application's dependencies with ease
- Service Providers: Organize your code with a clean, modular architecture
- Singleton and Transient Services: Full control over service lifetimes
- WordPress-Optimized: Built specifically for WordPress hooks and architecture
- Bootable Services: Optional boot process for service initialization
- Lightweight: Minimal overhead with maximum flexibility
- Type-Safe: Full PHP 8.1+ type declarations for better IDE support
- PHP 8.1 or higher
- WordPress (recommended latest version)
- Composer
Install via Composer:
composer require x3p0-dev/x3p0-frameworkImportant: If you're releasing this as part of a theme or plugin bundle, please vendor prefix your installation to avoid conflicts with other plugins/themes.
First, define the services your application needs:
<?php
namespace Your\Project;
class ServiceA implements ServiceAInterface
{
public function doSomething(): void
{
// Your implementation
}
}
class ServiceB
{
public function __construct(
private ServiceAInterface $serviceA
) {}
public function boot(): void
{
// Bootstrap code
}
}Extend the ServiceProvider base class to register your services:
<?php
namespace Your\Project;
use X3P0\Framework\Contracts\Bootable;
use X3P0\Framework\Core\ServiceProvider;
final class YourServiceProvider extends ServiceProvider implements Bootable
{
public function register(): void
{
// Register an abstract/interface with a concrete implementation.
// `transient()` creates a new instance each time.
$this->container->transient(
ServiceAInterface::class,
ServiceA::class
);
// Register a concrete implementation.
// `singleton()` creates a single instance and reuses it.
$this->container->singleton(ServiceB::class);
}
// Implementing `Bootable` is optional but useful for bootstrapping.
public function boot(): void
{
$this->container->get(ServiceB::class)->boot();
}
}Extend the Application base class to define your plugin/theme configuration:
<?php
namespace Your\Project;
use X3P0\Framework\Core\Application;
final class Plugin extends Application
{
/**
* Defines the plugin's namespace, used as a hook prefix.
*/
protected const NAMESPACE = 'your/plugin';
/**
* Defines the plugin's service providers.
*/
protected const PROVIDERS = [
YourServiceProvider::class
];
}Create a helper function to access your application instance:
<?php
namespace Your\Project;
use X3P0\Framework\Container\ServiceContainer;
use X3P0\Framework\Core\Application;
function plugin(): Application
{
static $plugin;
if (! $plugin instanceof Plugin) {
$plugin = new Plugin(new ServiceContainer());
}
return $plugin;
}<?php
/**
* Plugin Name: Your Plugin
* Plugin URI: https://example.com
* Description: Your plugin description
* Version: 1.0.0
* Author: Your Name
*/
namespace Your\Project;
// Autoload dependencies.
require_once __DIR__ . '/vendor/autoload.php';
// Initialize the plugin.
add_action('plugins_loaded', plugin(...), 9999);
// Boot registered services.
add_action('plugins_loaded', fn() => plugin()->boot(), PHP_INT_MAX);The service container manages the creation and lifecycle of your application's objects. It supports three binding types:
Creates a single instance that's reused throughout the application:
$this->container->singleton(MyServiceInterface::class, MyService::class);Creates a new instance each time it's requested:
$this->container->transient(MyServiceInterface::class, MyService::class);Registers an existing instance with the container, which is reused throughout the application:
$this->container->instance('my-custom-instance', new MyCustomInstance());Service providers are the central place to configure your container bindings. They have two main methods:
register(): Register bindings in the containerboot(): Execute bootstrapping code (optional, requires implementingBootable)
The application class serves as the central hub of your plugin/theme:
- Manages service providers
- Provides a hook namespace for WordPress integration
- Orchestrates the boot process
Retrieve services from the container:
$service = plugin()->container()->get(ServiceA::class);Or from within a service provider:
$service = $this->container->get(ServiceA::class);Register multiple service providers in your application:
final class App extends Application
{
protected const NAMESPACE = 'your/plugin';
protected const PROVIDERS = [
CoreServiceProvider::class,
AdminServiceProvider::class,
FrontendServiceProvider::class,
];
}The container automatically resolves dependencies:
class MyService
{
public function __construct(
private DependencyA $dependencyA,
private DependencyB $dependencyB
) {}
}
// The container will automatically inject DependencyA and DependencyB.
$this->container->singleton(MyService::class);Each service provider should handle a specific domain or feature:
// Good
class AdminServiceProvider extends ServiceProvider { /* ... */ }
class ApiServiceProvider extends ServiceProvider { /* ... */ }
// Avoid
class EverythingProvider extends ServiceProvider { /* ... */ }Bind interfaces to implementations for easier testing and flexibility:
$this->container->singleton(
CacheInterface::class,
TransientCache::class
);Use the service provider's boot() method for operations that require all services to be registered:
public function boot(): void
{
// Runs a service's `init()` method.
$this->container->get(MyService::class)->init();
}If you're distributing your plugin/theme, consider using a tool like PHP-Scoper to avoid conflicts.
X3P0 Framework is licensed under the GPL-2.0-or-later license.
Created and maintained by Justin Tadlock under the X3P0 umbrella.
Note: This framework is designed for modern PHP development. If you need to support older PHP versions, please consider using a different solution or forking this project.