Pollora - фреймворк, який запускає WordPress усередині Laravel-застосунку. Laravel стартує першим і обробляє фронтенд-запити своїм маршрутизатором, контролерами й Blade, а адмінка WordPress, його база й плагіни працюють як на звичайному сайті. Проєкт на цьому тижні розібрали на Laravel News, і він зачіпає знайому багатьом студіям ситуацію: клієнти сидять у WordPress, а команда пише на Laravel.
Досі тут було два шляхи. Або писати тему з functions.php, де реєстрація post types і хуків розмазана по викликах функцій, або тримати окремий Laravel-застосунок і читати таблиці WordPress збоку. Pollora пропонує третій: клієнт лишається у звичній адмінці, а код пишеться по-ларавелівськи.
Як це влаштовано
Проєкт - це Laravel-застосунок: public/index.php є фронт-контролером Laravel, і routes/web.php перевіряється першим. Composer ставить ядро WordPress у public/cms, а wp-content лежить у public/content - структура в дусі Bedrock. Pollora завантажує WordPress під час старту Laravel, з конфігурацією й підключенням до бази даних Laravel.
WordPress, як і раніше, розбирає кожен запит, тому умовні теги на кшталт is_single() працюють. Але відповідь рендерить уже Laravel.
Новий проєкт створюється через Composer або Pollora CLI, який вміє ще й підняти середовище в DDEV:
composer create-project pollora/pollora my-project
# або
composer global require pollora/cli
pollora new my-project --ddev
Після встановлення залежностей запускається інтерактивне налаштування: .env з доступами до бази, потім установлення WordPress з назвою сайту, мовою й адміністратором. Обидва кроки можна повторити вручну командами php artisan pollora:env:setup і php artisan pollora:install, а для CI в pollora:install усе передається опціями.
Маршрути на умовних тегах WordPress
Pollora додає до маршрутизатора Route::wp() і Route::wpMatch(). Вони зіставляють запит з умовним тегом WordPress - is_page(), is_single() тощо, - причому можна писати і назву функції, і коротку форму на кшталт 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']);
Описувати маршрут для кожної сторінки не треба. Якщо жоден не підійшов, Pollora йде ієрархією шаблонів WordPress і рендерить відповідне Blade-представлення: сторінка «About» візьме page-about.blade.php, а якщо його немає - page.blade.php.
Post types, хуки і REST - атрибутами
Замість register_post_type() у functions.php post type оголошується класом. Pollora знаходить його сам і генерує slug та підписи з назви класу:
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 і filters, причому один метод може слухати кілька хуків:
#[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);
}
Атрибутами оголошуються й таксономії (#[Taxonomy]), REST-маршрути (#[WpRestRoute]), задачі за розкладом (#[Schedule]), а також команди WP-CLI та AJAX-обробники. Заготовки класів генерують Artisan-команди на кшталт pollora:make:post-type і pollora:make:action.
Blade, блоки, медіа й Eloquent
- Теми - Blade-шаблони з Sage Directives (
@posts, @title, @content), Tailwind CSS і Vite через @roots/vite-plugin. Підтримуються батьківські й дочірні теми.
- Gutenberg-блоки створює
php artisan pollora:make:block hero-banner --theme: block.json, JSX-файли для редактора і Blade-шаблон. Шаблон рендерить блок на кожен запит, тож зміна розмітки одразу оновлює всі сторінки з ним, а прев'ю в редакторі береться з того самого шаблону.
- Медіатека переїжджає на будь-який диск з
config/filesystems.php - S3, R2, MinIO - двома змінними MEDIA_DISK і MEDIA_URL. WordPress далі користується своїми функціями завантаження, тому ACF і WooCommerce працюють без змін. Розміри зображень оголошуються в PHP через ImageSize і генеруються на вимогу.
- Дані WordPress доступні через Eloquent-моделі
Pollora\Models\Post, Page, Term, User та інші. Вони побудовані на Colt - форку Corcel, тож запити в стилі Corcel теж працюють.
- Для AI-агентів є пакет Nectar: настанови, навички агентів і MCP-інструменти для Pollora поверх Laravel Boost.
Чим відрізняється від Acorn, Sage і Corcel
На сайті проєкту є чесне порівняння з інструментами, які вже поєднують Laravel і WordPress. Головна різниця - порядок старту:
- Acorn - пакет, який приносить компоненти Laravel у WordPress. WordPress стартує першим, Acorn запускається з теми чи плагіна. Підходить, щоб додати Laravel в наявний сайт без зміни структури.
- Sage - стартова тема з Blade, Tailwind CSS і Vite для звичайного WordPress. Якщо потрібна лише тема, автори Pollora самі радять Sage як простіший вибір.
- Radicle - найближчий аналог від команди Roots: готовий проєкт з Acorn, Bedrock і Sage, але платний (80 доларів за один сайт, 240 - без обмежень), і WordPress там знову стартує першим.
- Corcel - не фреймворк, а набір Eloquent-моделей над таблицями WordPress. Сам WordPress не завантажується: ні хуків, ні плагінів. Добрий вибір, коли WordPress - лише бек-офіс для редакторів, а сайт повністю ваш.
Pollora - це протилежна схема: Laravel-застосунок, у якому живе WordPress. Порівняння відкрито визнає й борг перед Roots: Pollora використовує Bedrock-структуру, @roots/vite-plugin і Sage Directives.
Вимоги й стан проєкту
- PHP 8.4+ - не через сам фреймворк, а через Symfony 8 у
composer.lock скелета;
- Composer 2, Node.js і npm для збірки ассетів;
- MySQL 5.7+ або MariaDB 10.3+. Документація прямо каже, що WordPress завантажується лише з драйвером
mysql, а SQLite не підтримується, хоча README скелета SQLite ще згадує - орієнтуйтеся на документацію;
- WordPress 7.1+, який Composer ставить сам.
Версії Pollora йдуть за випусками Laravel: останній випуск pollora/framework - v13.39.1 від 29 жовтня, і пакет залежить від компонентів Laravel 13.39. Ліцензія - MIT, проєкт безкоштовний, розробляє його RuBee group. У власному порівнянні автори називають Pollora молодим проєктом, тоді як в Acorn - близько 2,66 млн установок на Packagist.
Чи варто братися
Компроміси тут архітектурні, і їх варто зважити заздалегідь:
- Кожен вебзапит завантажує WordPress і всі його плагіни. Laravel-маршрут, який до WordPress жодного стосунку не має, однаково платить за старт ядра й плагінів. На сайті з двома десятками важких плагінів це відчутно.
- Ядро WordPress оновлюється лише через Composer. Кнопка «Оновити» в адмінці більше не ваш інструмент - оновлення йде через деплой. Для команди з CI це скоріше плюс, для клієнта, який звик оновлювати все сам, - зміна процесу, яку треба проговорити.
- Теми WordPress як такі зникають. Фронтенд повністю переходить до Laravel, тож тема з маркетплейсу тут не допоможе.
- Молодий проєкт. Випуски виходять часто, і в журналі змін трапляються вимоги переглянути власний код - як-от перехід на Colt 11 у v13.39.1, після якого моделі, що перевизначають методи Colt, мають мати сумісні типи повернення.
Кому це підходить: студіям, які регулярно роблять клієнтські сайти на WordPress і хочуть писати їх з маршрутами, контролерами, чергами й тестами Laravel. Почати варто з невеликого нового проєкту, а не з міграції живого сайту: окремого посібника з переходу із Sage чи Acorn поки немає, хоча Blade-шаблони, Sage Directives і Vite-збірка переносяться майже без змін.