Skip to content

WP Packages is our new WPackagist replacement that's 17x faster and updates every 5 minutes

Acorn

Integrate WordPress & Laravel

Bring Laravel’s developer experience to WordPress

Use Blade, migrations, routing, and more without leaving WordPress

~/Code/

$ composer require roots/acorn
$ wp acorn

USAGE: wp acorn [command] [options] [arguments]

about                 Display basic information about your application
clear-compiled        Remove the compiled class file
completion            Dump the shell completion script
db                    Start a new database CLI session
env                   Display the current framework environment
help                  Display help for a command
list                  List commands
migrate               Run the database migrations
optimize              Cache framework bootstrap, configuration, and metadata to increase performance
test                  Run the application tests

acorn:init            Initializes required paths in the base directory
acorn:install         Install Acorn into the application

cache:clear           Flush the application cache
cache:forget          Remove an item from the cache

config:cache          Create a cache file for faster configuration loading
config:clear          Remove the configuration cache file

db:seed               Seed the database with records
db:table              Display information about the given database table
db:wipe               Drop all tables, views, and types

key:generate          Set the application key

make:command          Create a new Artisan command
make:component        Create a new view component class
make:composer         Create a new view composer class
make:controller       Create a new controller class
make:job              Create a new job class
make:middleware       Create a new HTTP middleware class
make:migration        Create a new migration file
make:model            Create a new Eloquent model class
make:provider         Create a new service provider class
make:queue-batches-table  Create a migration for the batches database table
make:queue-failed-table   Create a migration for the failed queue jobs database table
make:queue-table      Create a migration for the queue jobs database table
make:seeder           Create a new seeder class

migrate:fresh         Drop all tables and re-run all migrations
migrate:install       Create the migration repository
migrate:refresh       Reset and re-run all migrations
migrate:reset         Rollback all database migrations
migrate:rollback      Rollback the last database migration
migrate:status        Show the status of each migration

optimize:clear        Remove the cached bootstrap files

package:discover      Rebuild the cached package manifest

queue:clear           Delete all of the jobs from the specified queue
queue:failed          List all of the failed queue jobs
queue:flush           Flush all of the failed queue jobs
queue:forget          Delete a failed queue job
queue:listen          Listen to a given queue
queue:monitor         Monitor the size of the specified queues
queue:pause           Pause job processing for a specific queue
queue:prune-batches   Prune stale entries from the batches database
queue:prune-failed    Prune stale entries from the failed jobs table
queue:restart         Restart queue worker daemons after their current job
queue:resume          Resume job processing for a paused queue
queue:retry           Retry a failed queue job
queue:retry-batch     Retry the failed jobs for a batch
queue:work            Start processing jobs on the queue as a daemon

route:cache           Create a route cache file for faster route registration
route:clear           Remove the route cache file
route:list            List all registered routes

schedule:clear-cache  Delete the cached mutex files created by scheduler
schedule:interrupt    Interrupt the current schedule run
schedule:list         List all scheduled tasks
schedule:run          Run the scheduled commands
schedule:test         Run a scheduled command
schedule:work         Start the schedule worker

vendor:publish        Publish any publishable assets from vendor packages

view:cache            Compile all of the application's Blade templates
view:clear            Clear all compiled view files

$ wp acorn optimize

INFO Caching framework bootstrap, configuration, and metadata.

config .............................................................. 9.30ms DONE
events ............................................................. 29.91ms DONE
routes .............................................................. 4.99ms DONE
views .............................................................. 50.15ms DONE

Blade templates in WordPress

Use Laravel’s powerful Blade templating engine throughout WordPress. Create cleaner, more maintainable templates with layouts, components, and directives. Render WordPress blocks, emails, and more with the template engine loved by PHP developers worldwide.

Rendering WordPress blocks with Blade

views/blocks/button.blade.php

<x-button
    variant="{{ $variant }}"
    class="{{ $classes }}"
    href="{{ $href }}"
>
    {{ $text }}
</x-button>

Example Blade template

views/layouts/app.blade.php

<div class="flex flex-col h-screen">
    <div>
        @include('sections.header')
    </div>

    <main>
        @yield('content')
    </main>

    @include('sections.footer')
</div>

Eloquent models for WordPress data

Use Laravel’s powerful Eloquent ORM to interact with WordPress data. Create models for posts, users, and custom tables with relationships, scopes, and clean query syntax.

WordPress Post model

app/Models/Post.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';
    protected $primaryKey = 'ID';

    protected $fillable = [
        'post_title',
        'post_content',
        'post_status',
        'post_type',
    ];

    public function author()
    {
        return $this->belongsTo(User::class, 'post_author');
    }

    public function meta()
    {
        return $this->hasMany(PostMeta::class, 'post_id');
    }

    public function scopePublished($query)
    {
        return $query->where('post_status', 'publish');
    }
}

Using the model in a controller

app/Http/Controllers/PostController.php

<?php

// Get published posts with authors
$posts = Post::published()
    ->with('author')
    ->latest()
    ->paginate(10);

// Create new post
$post = Post::create([
    'post_title' => 'Hello World',
    'post_content' => 'Content here',
    'post_status' => 'publish',
    'post_type' => 'post',
]);

Laravel migrations for your WordPress projects

Use Laravel’s migration system to manage your WordPress database schema. Create, modify, and version your database structure with elegant PHP syntax.

Create & run migrations via WP-CLI

/srv/www/example.com

$ wp acorn make:migration

┌ What should the migration be named? ─────┐
 create_example_table                     
└──────────────────────────────────────────┘

INFO Migration [create_example_table.php] created successfully.

$ wp acorn migrate

INFO Running migrations.

create_example_table ...................... DONE

Migration file example

database/migrations/create_example_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class () extends Migration {
    public function up()
    {
        Schema::create('example', function (Blueprint $table) {
            $table->id();
            $table->string('example');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('example');
    }
};

Laravel routing in WordPress

Create virtual pages and custom endpoints without wrestling with WordPress rewrite rules. Define routes with clean syntax, middleware support, and named routes.

Registering routes

routes/web.php

<?php

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

Route::get('/welcome/', function () {
    return view('welcome');
});

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

Error handling & logging

Capture and diagnose errors more effectively with Laravel’s exception handling and logging. Track issues in development and production with structured logs.

Advanced logging

example.php

<?php

use Illuminate\Support\Facades\Log;

Log::debug('👋 Howdy');

Log::info('Processing order', [
    'order_id' => 123,
    'user_id' => 42,
    'total' => 99.99
]);

Log::error('Failed to send email', [
    'recipient' => '[email protected]',
    'exception' => $e->getMessage()
]);

Background jobs & queues

Process heavy tasks asynchronously with Laravel’s queue system. Perfect for image processing, email sending, data imports, or any task that shouldn’t block WordPress requests.

Queue setup & processing

/srv/www/example.com

$ wp acorn make:queue-table

INFO Migration [create_jobs_table.php] created successfully.

$ wp acorn migrate

INFO Running migrations.

create_jobs_table .......................... DONE

$ wp acorn queue:work

INFO Processing jobs...

Background job example

app/Jobs/ProcessImageUpload.php

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessImageUpload implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public int $attachmentId
    ) {}

    public function handle(): void
    {
        $attachment = get_post($this->attachmentId);
        $file = get_attached_file($this->attachmentId);

        // Generate thumbnails
        wp_generate_attachment_metadata($this->attachmentId, $file);

        // Optimize image
        $this->optimizeImage($file);

        // Update post meta
        update_post_meta($this->attachmentId, '_processed', true);
    }

    private function optimizeImage(string $file): void
    {
        // Custom image optimization logic
    }
}

Custom WP-CLI commands

Extend WordPress with custom Artisan commands accessible via WP-CLI. Build powerful maintenance tools, data migration scripts, and automated tasks that integrate seamlessly with your WordPress workflow.

Creating custom commands

/srv/www/example.com

$ wp acorn make:command CleanupDraftsCommand

INFO Console command [app/Console/Commands/CleanupDraftsCommand.php] created successfully.

$ wp acorn wp:cleanup-drafts --days=7

INFO Cleaning up drafts older than 7 days...
INFO Deleted 23 old draft posts.

Command implementation

app/Console/Commands/CleanupDraftsCommand.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Post;

class CleanupDraftsCommand extends Command
{
    protected $signature = 'wp:cleanup-drafts {--days=30 : Days to keep drafts}';

    protected $description = 'Clean up old draft posts';

    public function handle(): int
    {
        $days = $this->option('days');

        $this->info("Cleaning up drafts older than {$days} days...");

        $count = Post::where('post_status', 'draft')
            ->where('post_modified', '<', now()->subDays($days))
            ->delete();

        $this->info("Deleted {$count} old draft posts.");

        return Command::SUCCESS;
    }
}

Controllers for clean APIs

Build robust REST APIs and handle requests with Laravel controllers. Clean separation of concerns, validation, and response formatting for WordPress integrations.

Middleware for request filtering

Filter and transform requests before they reach your application. Handle authentication, rate limiting, CORS, and custom business logic with reusable middleware.

API controller

app/Http/Controllers/PostController.php

<?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()
            ->with('author')
            ->latest()
            ->paginate(10);

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

    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(),
        ]);

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

Authentication middleware

app/Http/Middleware/AuthenticateAdmin.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AuthenticateAdmin
{
    public function handle(Request $request, Closure $next)
    {
        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);
    }
}

Supported Laravel components

  • illuminate/auth
  • illuminate/bus
  • illuminate/cache
  • illuminate/collections
  • illuminate/conditionable
  • illuminate/config
  • illuminate/console
  • illuminate/container
  • illuminate/contracts
  • illuminate/cookie
  • illuminate/database
  • illuminate/encryption
  • illuminate/events
  • illuminate/filesystem
  • illuminate/hashing
  • illuminate/http
  • illuminate/log
  • illuminate/macroable
  • illuminate/pagination
  • illuminate/pipeline
  • illuminate/queue
  • illuminate/routing
  • illuminate/session
  • illuminate/support
  • illuminate/validation
  • illuminate/view
  • Sponsors

    Roots is an independent open source org, supported only by developers like you. Become a sponsor.

    Subscribe for updates

    Join over 8,000 subscribers for the latest Roots updates, WordPress plugin recommendations, modern WordPress projects, and web development tips.

    One last step! Check your email for a verification link.