dbout / wp-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.
Requires
- php: >=8.3
- illuminate/config: ^12.3 || ^13.0
- illuminate/container: ^12.3 || ^13.0
- illuminate/contracts: ^12.3 || ^13.0
- illuminate/events: ^12.3 || ^13.0
- illuminate/log: ^12.3 || ^13.0
- illuminate/support: ^12.3 || ^13.0
- nesbot/carbon: ^3.8.4
- psr/cache: ^3.0
- psr/log: ^2.0 || ^3.0
- symfony/cache: ^6.4.40
- symfony/http-foundation: ^6.4.46
- symfony/property-access: ^6.4.3 || ^7.0.3
- symfony/routing: ^6.4.41
- symfony/translation-contracts: ^3.4.2
- symfony/validator: ^6.4.11
- twig/twig: ^3.27
Requires (Dev)
- antecedent/patchwork: 2.2.4
- brain/monkey: 2.7.0
- friendsofphp/php-cs-fixer: 3.95.27
- mockery/mockery: 1.6.15
- php-stubs/wordpress-stubs: 6.9.4
- php-stubs/wp-cli-stubs: 2.12.0
- phpstan/phpstan: 2.3.4
- phpunit/phpunit: 12.5.42
- rector/rector: 2.8.3
- roots/wordpress: 7.1.4
Suggests
- ext-gd: Required by the towebp Twig filter (with the WebP support)
- wp-cli/wp-cli: Required by the commands
Provides
None
Conflicts
- monolog/monolog: <3.8
- symfony/cache-contracts: <2.5.3 || >=3.0,<3.4.2
- symfony/clock: <6.4.3 || >=7.0,<7.0.3
- symfony/polyfill-php83: <1.30
- symfony/property-info: <5.4.35 || >=6.0,<6.4.3 || >=7.0,<7.0.3
- symfony/string: <5.4.35 || >=6.0,<6.4.3 || >=7.0,<7.0.3
- symfony/var-exporter: <6.4.3 || >=7.0,<7.0.3
Replaces
None
This package is auto-updated.
Last update: 2026-11-01 14:18:18 UTC
README
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.