Skip to content
Acorn

Help us continue to build and maintain our open source projects. We’re a small team of independent developers and every little bit helps.

Controllers, Middleware, and HTTP Kernel in WordPress

View as Markdown:

Acorn brings Laravel's controller and middleware system to WordPress, enabling you to build robust APIs, handle complex request logic, and implement clean separation of concerns. Controllers organize your route logic, while middleware provides a convenient mechanism for filtering HTTP requests.

We recommend referencing the Laravel docs on Controllers and Middleware for a complete understanding.

Creating controllers

Generate a controller

To create a new controller, use the make:controller Artisan command:

Create a basic controller

$ wp acorn make:controller PostController

Create an API resource controller

$ wp acorn make:controller PostController --api

Create a controller with all CRUD methods

$ wp acorn make:controller PostController --resource

This creates a new controller file in app/Http/Controllers/.

Basic controller example

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Models\Post;

class PostController extends Controller
{
    public function index(): JsonResponse
    {
        $posts = Post::published()
            ->latest('ID')
            ->take(10)
            ->get();

        return response()->json($posts);
    }

    public function show(int $id): JsonResponse
    {
        $post = Post::findOrFail($id);
        return response()->json($post);
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
            'status' => 'in:draft,publish'
        ]);

        $post = Post::create([
            'post_title' => $validated['title'],
            'post_content' => $validated['content'],
            'post_status' => $validated['status'] ?? 'draft',
            'post_type' => 'post',
            'post_author' => get_current_user_id() ?: 1,
        ]);

        return response()->json($post, 201);
    }
}

Using controllers in routes

Define your routes in routes/web.php:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;

// Individual routes
Route::get('/api/posts', [PostController::class, 'index']);
Route::get('/api/posts/{id}', [PostController::class, 'show']);
Route::post('/api/posts', [PostController::class, 'store']);

// Resource routes (generates all CRUD routes)
Route::resource('/api/posts', PostController::class);

// API resource routes (excludes create/edit forms)
Route::apiResource('/api/posts', PostController::class);

Working with WordPress data

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class WordPressController extends Controller
{
    public function createPost(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
        ]);

        $post_id = wp_insert_post([
            'post_title' => $validated['title'],
            'post_content' => $validated['content'],
            'post_status' => 'publish',
            'post_type' => 'post',
        ]);

        return response()->json(['id' => $post_id], 201);
    }
}

Creating middleware

Generate middleware

To create new middleware, use the make:middleware Artisan command:

$ wp acorn make:middleware AuthenticateAdmin

This creates a new middleware file in app/Http/Middleware/.

Authentication middleware example

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class AuthenticateAdmin
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!is_user_logged_in()) {
            return response()->json([
                'message' => 'Authentication required'
            ], 401);
        }

        if (!current_user_can('manage_options')) {
            return response()->json([
                'message' => 'Admin access required'
            ], 403);
        }

        return $next($request);
    }
}

Applying middleware

Apply middleware to routes:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
use App\Http\Middleware\AuthenticateAdmin;

Route::post('/api/posts', [PostController::class, 'store'])
    ->middleware(AuthenticateAdmin::class);

Customizing the HTTP kernel

For most middleware needs, use the withMiddleware() method when booting Acorn. If you need more control, you can override the HTTP kernel entirely.

Creating a custom kernel

Create a custom kernel class that extends Acorn's HTTP kernel. When overriding properties like $middleware, make sure to include any defaults you still need — setting the property replaces the parent's values entirely:

<?php

namespace App\Http;

use Roots\Acorn\Http\Kernel as AcornHttpKernel;

class Kernel extends AcornHttpKernel
{
    public function __construct(\Illuminate\Contracts\Foundation\Application $app, \Illuminate\Routing\Router $router)
    {
        $this->middleware[] = \Illuminate\Foundation\Http\Middleware\TrimStrings::class;

        parent::__construct($app, $router);
    }
}

Registering the custom kernel

Override the kernel singleton by rebinding it before boot(). The kernel is resolved during boot, so the binding must be in place before that happens:

use Roots\Acorn\Application;

add_action('after_setup_theme', function () {
    $builder = Application::configure()
        ->withProviders()
        ->withRouting(
            web: base_path('routes/web.php'),
            wordpress: true,
        );

    app()->singleton(
        \Illuminate\Contracts\Http\Kernel::class,
        \App\Http\Kernel::class
    );

    $builder->boot();
}, 0);

Last updated