The Problem
Recently whilst working on an outsourced project at We Are DWM we had a Laravel app and a WordPress site running side by side. The client had wanted the same design across both “sites” and for it to appear as seamless as possible.
This really gave us two options:
- Maintain two separate sets of CSS and templates, one for WordPress and another for Laravel, or
- Find a way to merge the two without compromising their integrity.
Option 1 is probably the simplest option, but would more than likely lead to a huge number of issues later down the line, with one set of styles being updated but not the others, etc. Therefore I decided to research option 2 some more and run with it.
The Solution
Seeing as WordPress is bootstrapped through the wp-load.php
file, as long as we can load this file we should have access to our WordPress functions. That sounds easy enough, just require the wp-load.php
file in your routes I hear you say? But I only need WordPress for a certain subset of routes, specifically the user facing ones. This is how I did it:
Set up your routes
Setting up the routes was my first task, in order to hook into these routes later, I added a custom attribute to my route group, called “name”:
Route::group(['name' => 'frontend'], function (){ Route::get(...); });
Load WordPress using a Service Provider
I then created a service provider that I could use to load my wp-load.php
file using php artisan make:provider WordPressServiceProvider
.
Note: I did not add this provider to my providers
array in the config/app.php
file.
Here’s the content of that file:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use URL; class WordPressServiceProvider extends ServiceProvider { /** * Path to our WP installation * * @var string */ protected $bootstrapFilePath = '../path/to/wp/and/wp-load.php'; /** * Bootstrap the application services. * * @return void */ public function boot() { /** * Here we can enqueue any extra scripts or styles we may need. * I loaded my frontend specific styles and scripts that were of no use to the WP site */ wp_enqueue_style('frontend-styles', URL::asset('css/frontend.css'), ['dependencies'], false); wp_enqueue_script('frontend-scripts', URL::asset('js/frontend.js'), ['dependencies'], false, true); } /** * Register the application services. * * @return void */ public function register() { if(\File::exists($this->bootstrapFilePath)) { require_once($this->bootstrapFilePath); } } }
Put it all together with some Middleware
Finally, in order to load my service provider at the required time, I need to tell it when that is. I decided that a simple piece of middleware would be the best option for this. Using the following command I created the middleware below php artisan make:middleware WordPressLoader
.
<?php namespace App\Http\Middleware; use Closure; class WordPressLoader { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $actions = $request->route()->getAction(); // Make sure out custom name attribute is set and equals frontend if(isset($actions['name']) && $actions['name'] == 'frontend') { // Register our service provider app()->register(\App\Providers\WordpressServiceProvider::class); } return $next($request); } }
The above code registers our new service provider with Laravel if the custom route attribute “name” exists and it equals “frontend”. If these conditions don’t match, we just skip over this and continue with the rest of our middleware.
Note: Don’t forget to add this middleware to your $middlewareGroups
array in Http/Kernel.php
Using WordPress
Now that you have WordPress loaded when you need it, you can use any of the standard WP functions within your Blade templates, such as wp_head()
and wp_nav_menu()
. Neat, eh?