Laravel Packages

Pollora: Run WordPress Inside a Laravel Application

Published
Pollora: Run WordPress Inside a Laravel Application image

Pollora is a framework that runs WordPress inside a Laravel application. Laravel boots first and handles front-end requests with its router, controllers, and Blade, while the WordPress admin, database, and plugins keep working.

Here's what the framework gives you:

  • WordPress-aware routing: Laravel routes on conditional tags, with the template hierarchy as a fallback
  • Attribute registration: post types, taxonomies, hooks, and REST routes declared as PHP attributes
  • Blade themes and blocks: Blade views, Vite assets, and Gutenberg blocks rendered with Blade
  • Eloquent models: WordPress data through Colt, a fork of Corcel
  • Media storage: the media library on any Laravel disk, including S3 and R2
  • Agent tooling: Pollora guidelines and MCP tools through Laravel Boost

How Pollora Runs WordPress

Composer installs WordPress core into public/cms, and Pollora loads it while Laravel boots, using your Laravel config and database connection. WordPress still parses each request, so conditional tags like is_single() work as usual, but Laravel renders the response. The admin dashboard at /cms/wp-admin/ works like it does on any WordPress site.

Because both frameworks run together, every web request boots WordPress and its plugins. WordPress core updates go through Composer instead of the dashboard.

Routing on WordPress Conditional Tags

Pollora adds Route::wp() and Route::wpMatch() to the router. They match a request against a WordPress conditional tag such as is_page() or is_single(), and you can use either the function name or a short alias like page:

use App\Http\Controllers\FormController;
use App\Models\Feature;
use Illuminate\Support\Facades\Route;
 
Route::wp('single', function () {
return view('post');
});
 
Route::wp('template', 'landing', function () {
return view('page.landing', [
'features' => Feature::all(),
]);
});
 
Route::wpMatch(['GET', 'POST'], 'page', ['contact', 'request-a-quote'], [FormController::class, 'index']);

You don't need a route for every page. When nothing matches, Pollora follows the WordPress template hierarchy and renders the matching Blade view, so an "About" page uses page-about.blade.php if it exists and falls back to page.blade.php.

Post Types and Hooks as PHP Attributes

Instead of calling register_post_type() in functions.php, you declare a post type as a class. Pollora discovers it and generates the slug and labels from the class name:

namespace App\Cms\PostTypes;
 
use Pollora\Attributes\PostType;
use Pollora\Attributes\PostType\HasArchive;
use Pollora\Attributes\PostType\MenuIcon;
use Pollora\Attributes\PostType\PubliclyQueryable;
use Pollora\Attributes\PostType\Supports;
 
#[PostType]
#[PubliclyQueryable]
#[HasArchive]
#[Supports(['title', 'editor', 'thumbnail'])]
#[MenuIcon('dashicons-calendar')]
class Event
{
}

Actions and filters work the same way, and a method can listen to more than one hook:

namespace App\Cms\Hooks;
 
use Pollora\Attributes\Action;
use Pollora\Attributes\Filter;
 
class ContentHooks
{
#[Action('init', priority: 10)]
#[Action('wp_loaded', priority: 15)]
public function setup(): void
{
// ...
}
 
#[Filter('the_content', priority: 10)]
public function filterContent(string $content): string
{
return str_replace('ugly', 'shiny', $content);
}
}

Artisan commands like pollora:make:post-type and pollora:make:action generate these classes for you.

Gutenberg Blocks Rendered with Blade

The pollora:make:block command scaffolds a Gutenberg block with a block.json, JSX editor files, and a Blade template:

php artisan pollora:make:block hero-banner --theme

The Blade template renders the block on every request, so a markup change updates every page that uses it. The editor preview comes from the same template, and Pollora builds the block's assets with Vite.

Media on Laravel Storage Disks

Pollora can keep the WordPress media library on any disk in config/filesystems.php. Define the disk, then point Pollora at it in .env:

MEDIA_DISK=media
MEDIA_URL=https://media.example.com

WordPress keeps using its own upload functions, so plugins like ACF and WooCommerce work without changes. If you're new to S3 disks in Laravel, see using AWS S3 for Laravel storage.

How It Compares

Earlier projects combined Laravel and WordPress in other ways, such as the Themosis framework and Corcel, which reads WordPress tables from a Laravel app. Pollora publishes its own comparison with Acorn, Sage, Radicle, and Corcel:

Pollora Acorn Sage Radicle
What it is A Laravel application that runs WordPress A package that brings Laravel components into WordPress A WordPress starter theme A WordPress starter built on the Roots stack
Boot order Laravel first, WordPress inside it WordPress first, Acorn booted from a theme or plugin Loaded by WordPress as a theme WordPress first, with Acorn
Post types and hooks PHP attributes Theme or plugin code Theme code config/post-types.php
License and price MIT, free MIT, free MIT, free One-time purchase

The comparison suggests Sage for a theme on a standard WordPress install, Acorn for adding Laravel components to an existing site, and Corcel for a Laravel app that only reads WordPress data. It also describes Pollora as a young project, while Acorn and Sage have many more installs.

Installation

You can create a new project with Composer:

composer create-project pollora/pollora my-project

The installation guide covers the requirements, setup, the Pollora CLI, and DDEV. For coding agents, the Nectar package adds Pollora guidelines and MCP tools to Laravel Boost.

Pollora is MIT licensed. You can find the documentation at pollora.dev and the source in the Pollora repository on GitHub.

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

acquaintsoft logo
Acquaint Softtech

Hire Laravel developers with AI expertise at $20/hr. Get started in 48 hours.

Visit Acquaint Softtech

The latest

View all →
Scheduled Session Garbage Collection in Laravel 13.39 image

Scheduled Session Garbage Collection in Laravel 13.39

Read article
Deferred Schema Loading in Filament v5.8 image

Deferred Schema Loading in Filament v5.8

Read article
Sloppy: Static Analysis for AI-Written PHP image

Sloppy: Static Analysis for AI-Written PHP

Read article
Mastering Laravel Testing: A Video Course on Laravel Tests image

Mastering Laravel Testing: A Video Course on Laravel Tests

Read article
NativePHP Mobile Security Advisories: Update to 4.6.1 image

NativePHP Mobile Security Advisories: Update to 4.6.1

Read article
Volker Dusch on the PHP RCE Vulnerabilities and Disclosure image

Volker Dusch on the PHP RCE Vulnerabilities and Disclosure

Read article