eqxdev/wordpress-blade

Use the Laravel Blade templating engine in WordPress plugins and themes.

Maintainers

Package info

github.com/eqxDev/wordpress-blade

pkg:composer/eqxdev/wordpress-blade

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-02-18 20:27 UTC

This package is auto-updated.

Last update: 2026-03-18 20:36:08 UTC


README

Use the Laravel Blade templating engine in WordPress plugins and themes.

Requirements

  • PHP 8.2 or higher
  • Laravel/Illuminate 11.x or 12.x

Installation

composer require eqxdev/wordpress-blade

Usage

<?php

require 'vendor/autoload.php';

use EqxDev\Blade\Blade;

$viewsPath = __DIR__ . '/views';
$cachePath  = __DIR__ . '/cache';

$blade = new Blade($viewsPath, $cachePath);

// Render a view
echo $blade->view()->make('hello', ['name' => 'World'])->render();

Multiple View Directories

You can pass an array of directories to search for views:

$blade = new Blade([__DIR__ . '/views', __DIR__ . '/shared-views'], $cachePath);

Custom Event Dispatcher

If you need to provide your own event dispatcher (for example, to listen to view events):

use Illuminate\Events\Dispatcher;

$events = new Dispatcher;
$blade = new Blade($viewsPath, $cachePath, $events);

Accessing the Blade Compiler

Register custom directives by accessing the compiler directly:

$blade->getCompiler()->directive('datetime', function (string $expression): string {
    return "<?php echo ($expression)->format('Y-m-d H:i'); ?>";
});

Clearing the Compiled View Cache

Remove all compiled view files from the cache directory:

$blade->clearCache();

Using All Blade Features

This package supports all Blade features as described in the Laravel documentation: https://laravel.com/docs/12.x/blade

WordPress Integration

This package works as a Composer dependency for WordPress plugin and theme development.

Setup

use EqxDev\Blade\Blade;
use EqxDev\Blade\WordPressDirectives;

$blade = new Blade(
    get_template_directory() . '/views',
    wp_upload_dir()['basedir'] . '/blade-cache',
);

WordPressDirectives::register($blade->getCompiler());

For child themes, pass both the child and parent view directories:

$blade = new Blade(
    [get_stylesheet_directory() . '/views', get_template_directory() . '/views'],
    wp_upload_dir()['basedir'] . '/blade-cache',
);

Cache Directory

Use a dedicated path outside wp-content/cache/ to avoid WordPress caching plugins (WP Rocket, LiteSpeed Cache, WP Super Cache) from purging your compiled Blade templates:

// Good - dedicated directory
wp_upload_dir()['basedir'] . '/blade-cache'
WP_CONTENT_DIR . '/blade-cache'

// Bad - inside the cache directory managed by WP caching plugins
WP_CONTENT_DIR . '/cache/blade'

Cache Invalidation

Hook into WordPress events to clear compiled views when templates may have changed:

// Clear on theme switch and plugin/theme updates
add_action('after_switch_theme', fn () => $blade->clearCache());
add_action('upgrader_process_complete', fn () => $blade->clearCache());

// Hook into popular caching plugins
add_action('wp_cache_cleared', fn () => $blade->clearCache());             // WP Super Cache
add_action('rocket_after_clean_cache_busting', fn () => $blade->clearCache()); // WP Rocket
add_action('litespeed_purged_all', fn () => $blade->clearCache());          // LiteSpeed Cache

WordPress Directives

The WordPressDirectives class registers Blade directives for common WordPress functions that echo output directly (and therefore can't be used with {{ }}).

Output

Directive Equivalent
@wphead <?php wp_head(); ?>
@wpfooter <?php wp_footer(); ?>
@wpbodyclass <?php body_class(); ?>
@wpbodyclass('extra') <?php body_class('extra'); ?>
@wptitle <?php the_title(); ?>
@thecontent <?php the_content(); ?>
@theexcerpt <?php the_excerpt(); ?>

The WordPress Loop

@wploop
    <article>
        <h2>{{ get_the_title() }}</h2>
        @thecontent
    </article>
@wpempty
    <p>No posts found.</p>
@endwploop

Custom WP_Query

Automatically calls wp_reset_postdata() when the loop ends:

@wpquery(['post_type' => 'page', 'posts_per_page' => 5])
    <h2>{{ get_the_title() }}</h2>
@wpempty
    <p>No pages found.</p>
@endwpquery

Authentication

Directive Checks
@wpauth / @endwpauth is_user_logged_in()
@wpguest / @endwpguest ! is_user_logged_in()
@wprole('capability') / @endwprole current_user_can('capability')
@wpauth
    <p>Welcome, {{ wp_get_current_user()->display_name }}!</p>
@endwpauth

@wprole('manage_options')
    <a href="{{ admin_url() }}">Dashboard</a>
@endwprole

Hooks, Sidebars, and Shortcodes

Directive Equivalent
@wpaction('hook_name') <?php do_action('hook_name'); ?>
@wpfilter('hook', $value) <?php echo apply_filters('hook', $value); ?>
@wpsidebar('sidebar-id') <?php dynamic_sidebar('sidebar-id'); ?>
@wpshortcode('[gallery]') <?php echo do_shortcode('[gallery]'); ?>

Example Template

<!DOCTYPE html>
<html>
<head>
    @wphead
</head>
<body @wpbodyclass>
    @wpauth
        <p>Welcome back, {{ wp_get_current_user()->display_name }}!</p>
    @endwpauth

    @wploop
        <article>
            <h2>{{ get_the_title() }}</h2>
            @thecontent
        </article>
    @wpempty
        <p>No posts found.</p>
    @endwploop

    @wpsidebar('footer-widgets')
    @wpfooter
</body>
</html>

Development

# Run tests
composer test

# Run static analysis
composer analyse

# Check code style
composer lint

# Fix code style
composer fix

License

MIT