dbout/wp-foundation
| Install | |
|---|---|
composer require dbout/wp-foundation:dev-main |
|
| PHP: | >=8.3 |
| License: | MIT |
| Last Updated: | Nov 1, 2026 |
| Links: | GitHub · Packagist |
WordPress Foundation
Lightweight application foundation for WordPress: service container, attribute-based routing and WP-CLI commands, Twig views, validation, cache and security hardening, built on Symfony and Illuminate components.
Philosophy
WordPress is a great CMS, but building a business application on top of it often ends with code scattered in functions.php, global functions and hooks everywhere. This package brings the structure of a modern PHP application to WordPress, without replacing WordPress:
- WordPress stays in charge. The content, the admin, the plugins and the hooks work as usual: the package only adds what WordPress lacks (a container, controllers, a validator, ...). A URL without a route is handled by WordPress.
- Proven components, no reinvented wheel. The routing, the validation and the cache come from Symfony, the container and the logger from Illuminate: their documentation and their knowledge apply here.
- Configuration over code. The behavior is driven by configuration files merged with sensible defaults, and the classes are discovered from their PSR-4 namespaces: adding a controller or a command is adding a class.
- Lightweight and explicit. No magic: a provider registers services and adds hooks, a controller returns a response. The package stays small enough to be read and understood.
The best of Laravel and Symfony
Rather than choosing a side, the package takes from each framework what it does best, as standalone components:
- From Laravel, the developer experience: a container with automatic injection, service providers, facades, configuration files and a logger that are simple to use day to day.
- From Symfony, the robust and well-tested building blocks: routing, HTTP foundation, validation and cache, used by thousands of projects (Laravel itself relies on several of them).
Only these components are installed, not the full frameworks: WordPress keeps its own bootstrap, and the package stays light.
[!TIP] To simplify the integration of this library, we recommend using WordPress with Bedrock: the application lives next to WordPress and is installed with Composer.
Features
- ✅ Service container (Illuminate) with service providers and facades
- ✅ Configuration files merged with the default configuration of the package
- ✅ Routing with PHP attributes on top of Symfony Routing, controllers discovered from PSR-4 namespaces (wildcards supported)
- ✅ HTTP responses (view, redirect, JSON, errors) and HTTP exceptions
- ✅ WP-CLI commands declared with a
#[Command]attribute - ✅ Twig views with WordPress functions, assets (Vite manifest) and image resizing (WebP)
- ✅ Validation with Symfony Validator, messages translated with the WordPress translations
- ✅ Cache (Symfony Cache) disabled outside production, cleared with
wp app:cache:clear - ✅ Security hardening (HTTP headers, XML-RPC, REST API, user enumeration, ...)
[!TIP] Only the security protections without visible effect are enabled by default: enable the others (version, author pages, oEmbed, admin redirections) according to your site.
Requirements
| Requirement | Version | Used by |
|---|---|---|
| PHP | 8.3+ | |
| WordPress | 5.6+ | |
| WP-CLI | 2.x | The commands (optional) |
| PHP GD extension with WebP | The towebp filter (optional) |
WordPress must load the Composer autoloader (vendor/autoload.php), it is the case with Bedrock.
Installation
composer require dbout/wp-foundation
Documentation
The documentation is in the docs directory:
- Getting started
- Configuration reference
- Routing
- Views
- Validation
- Console
- Cache
- Images
- Logging
- Security
- Troubleshooting
Quick start
Create the application in a mu-plugin:
use Dbout\WpFoundation\Application;
$basePath = dirname(__DIR__, 3);
Application::configure($basePath)
->withPaths(config: $basePath . '/config', bootstrap: $basePath . '/bootstrap')
->create();
Declare where the controllers and the templates are:
// config/router.php
return [
'namespaces' => [
'App\\Controller\\',
],
];
// config/twig.php: the `views` directory of `app` is the `@app` Twig namespace
return [
'modules' => [
dirname(__DIR__) . '/app',
],
];
And add a controller:
namespace App\Controller;
use Dbout\WpFoundation\Http\Response\ResponseInterface;
use Dbout\WpFoundation\Http\Response\ViewResponse;
use Dbout\WpFoundation\Routing\Attribute\Route;
#[Route(path: '/hello/{name}', name: 'hello', methods: ['GET'])]
final class Hello
{
public function __invoke(string $name): ResponseInterface
{
return new ViewResponse('@app/hello.twig', ['name' => $name]);
}
}
See Getting started for the details.
Contributing
💕 🦄 We encourage you to contribute to this repository, so everyone can benefit from new features, bug fixes, and any other improvements. Have a look at our contributing guidelines to find out how to raise a pull request.
Related Packages
Application starter for the Ions PHP framework — a secure, structured host-app s...