Search by

dbout / wp-foundation

dimitriBouteille

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.

v1.0.0-rc.1 2026-11-01 14:15 UTC

This package is auto-updated.

Last update: 2026-11-01 14:18:18 UTC


README

GitHub Release Compatibility Tests Packagist Downloads

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:

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.