Integrating WordPress into Laravel

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:

  1. Maintain two separate sets of CSS and templates, one for WordPress and another for Laravel, or
  2. 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 (){



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:


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)) {

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.


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

        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?

Moving WordPress onto HTTPS

So recently I’ve been moving a fair few WordPress sites over to run completely on HTTPS and whilst this should be a simple URL switch, WordPress can make it a bit of a pain. Therefore, below is my preferred way of making the transition.

For the sake of this post, I’m going to assume you’ve already purchased and installed your SSL certificate (if you haven’t Namecheap are great!)

Step 1 – Site Address Change

This is the most basic step and will change all your WordPress URLs for you.

In your wp-admin section, go to Settings > General and change these two boxes to the URLs begin with https rather than http. Easy!

Screen Shot 2016-02-23 at 23.24.16

Step 2 – Asset URL Fix

You’ve probably noticed that although your site is now running over https, you’ve not got that nice green padlock, or alternatively it’s only appearing on certain pages. Damn! Let’s fix that for you.

The reason this is happening, is because all your assets (images etc.) that have been uploaded into posts or pages, store the full URL to the file. Because when you uploaded them your url started with http your assets were saved with the http URL.

Don’t despair, we can fix this pretty easily. You’ll need to install and activate a plugin called Better Search Replace, this plugin will allow you to find and replace content in your database and although this is fairly safe, it’s probably worth backing up your database before we go any further.

Screen Shot 2016-02-23 at 23.32.49

Once installed, go to Tools > Better Search Replace in your admin area. You want to add your domain with /wp-content on it in the Search For field, E.G. In the Replace With field, you want the same thing, but with the https version of the URL, E.G. Make sure you highlight all your tables in the Select tables section and 100% make sure that the Run as dry run? checkbox IS checked.

Screen Shot 2016-02-23 at 23.35.21

Now you can click the button at the bottom to run the search. It may take a few minutes depending on the size of your database and speed of the server, but it shouldn’t take too long. Once it’s finished, if you scroll to the top of the page, you should see something like the following.

Screen Shot 2016-02-23 at 23.41.52

Feel free to click to view more details if you’d like to check which tables contain the data to be changed.

Once you’re happy with this, you can scroll back down and uncheck the Run as dry run? checkbox. Now when you hit the button to run the script, it WILL replace the data in your database.

You may need to do this for the www. version of your site as well, depending on how your site is set up, E.G. Find and replace with

Step 3 – Check Your Site

Now we’ve made it this far, it’s a good time to check that your site is still functioning correctly and that your SSL is working. If it is, great! If it’s not, then you need to look at what’s not working.

If your site is not working at all, then you’ve probably messed something up with the database find and replace. Go ahead and restore that backup you took earlier, you did take a backup didn’t you? Good.

If the site is working correctly, but your SSL is still not working as expected (no green padlock) then we need to dig deeper. Go and do a dry run search and replace on your database for the http version of your site again, you shouldn’t get any hits this time, if you do then repeat step 2 until you don’t.

If you don’t get any hits, then generally it means that something you’re using is built badly. This is normally a hardcoded CSS or JavaScript URL in your theme or a plugin you’re using. If you can, try deactivating your plugins 1 by 1 until you find the culprit, then contact the plugin author and tell them to sort their code out!

Step 4 – Force SSL Site Wide

You can skip this step if you’d prefer, but seeing as we’re installing the SLL site wide, we might as well enforce it.

To do this, you’re going to need to update your .htaccess file. If you can access this through FTP or a control panel, do it that way. If not, you can use this plugin, but it’s a little risky if you mess something up.

Whichever way you do it, you’ll need to add the following code, but make sure you switch the URL for your new https URL:

<IfModule mod_rewrite.c>
RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$$1 [R=301,L]

You’ll need to add this above the # BEGIN WordPress line that should already be in the .htaccess file.

Step 6 – Check the Site Again

Now we’ve completed all the steps, check your site again. If you’re getting a 500 error then something is wrong with your .htaccess file. Revert your changes and ask someone who knows about development to take a look at it, .htaccess files can be a pain in the ass!

If your site is now running well over SSL then well done and we’re at the end of our journey together. Enjoy your secure site and let people thing you’re a genius!

How to allow SVG uploads in WordPress


Nope, stop.

You developers/bloggers who keep passing the below code around as a valid way of allowing SVG uploads in WordPress are killing me inside.

function cc_mime_types($mimes) {
    $mimes['svg'] = 'image/svg+xml';
    return $mimes;
add_filter('upload_mimes', 'cc_mime_types');

Yes, this will allow you to upload SVGs in WordPress, it will also allow someone to upload an XML Bomb or an SVG with an XXE attack or god forbid a lovely XSS attack. You see, too many developers are allowing SVG uploads without thinking about what that means. Seriously, why do you think WordPress hasn’t added SVG uploads into core yet? Not because they want to make life difficult but because they understand the security risks that are imposed by allowing an SVG to be uploaded.

There is currently, as far as I’m aware, no well tested PHP library for SVG sanitisation. There have been a few attempts but as far as I can tell, they’ve all been far too lenient on allowing potentially dangerous attributes through. To me, this means they either are too trusting, or don’t fully understand the potential payloads that can be embedded within an SVG.

The library I’ve been working on has taken the opposite stance. By default, be overly aggressive when stripping attributes and elements and then allow people to add their own whitelist if they need to. This, I think is the only feasible way of properly sanitising an SVG.

As for WordPress and SVGs, please stop using the above code. It makes me cringe every time I see it, especially when I think that this is actually in use on production sites. Fine, play with SVGs locally but to put this on a public facing server? Well, you’re a braver person than me.

Please people, use SVGs in your front end builds, use it as backgrounds, images, inline, whatever, but please stop allowing people to upload un-sanitised SVGs to the system. There’s no difference between allowing an SVG upload to allowing a PHP upload. For those of you that think that allowing a PHP upload is OK, because there’s obviously a fair few of you please stop developing. Seriously.


Why I hate the WordPress signup page

I’ve been working with WordPress multisite a lot recently and whilst all in all it’s not too bad, there is one thing that really pisses me off about it, wp-signup.php. No matter how many times I try and get my head round the contents of this file, I still struggle.

It just seems like this file is a complete cluster-fuck of functions, html and css. On top of that, I feel there are insufficient hooks and filters to allow you to customise it properly without hacking the file to pieces.

I’ve had to style up a few signup pages recently for a project of ours and it was that much of a pain in the ass, I ended up using Gravity Forms to create a custom signup page that was 100 times better looking and easier to style.

Now, I’m not saying that wp-signup.php is useless, it does it’s job and it seems to do it well, my only gripe is that it’s so unstructured and hard to customise. That’s something that can be fixed though and it’s my hope that someone will address this in time for WordPress 4.4. I think I may have a crack at it this week and see what happens, we’ll see though.

Sanitize SVGs in WordPress

So my plugin Safe SVG has just been accepted into the WordPress plugin directory. Whilst mainly a proof of concept, I’m hoping that this plugin will help convince the core team that SVGs, with the right sanitization should become part of core.

My major argument for allowing SVGs in core with sanitization is that there are currently 128 other SVG upload plugins in the plugin directory (source), plus the likes of the posts on blogs like CSS Tricks such as this one that all show you how to allow SVG uploads in WordPress, but don’t address or sometimes even mention the massive security risks that come with allowing users to upload SVGs.

SVGs should be considered as standalone XML applications, there are a huge number of vulnerabilities that can be attacked. For example, some of the easiest to implement are XXE attacks and the Billion Laughs attack. Safe SVG nullifies these attacks by removing the DOCTYPE from the SVG file, something so simple yet overlooked by most other plugins.

Safe SVG also protects against XSS attacks embedded within the XML file by defining a strict whitelist of elements and attributes allowed within the SVG, anything not on these whitelists are removed. Whilst this may break some Javascript powered SVG animations, I feel that is a small price to pay for peace of mind when it comes to your users security.

Probably the best way to learn more about Safe SVG is to go and download it from the WordPress plugin directory and take a look through the code, alternatively you can see the library it’s built upon on Github. If you find a bypass or have any suggestions on how to improve this plugin or the underlying library, please don’t hesitate to contact me and let me know your thoughts.

Safe SVG for WordPress

After a lot of testing of svg-sanitizer I’ve finally decided to make a WordPress plugin for it. This is more of a PoC to show that it can be done.

Once installed, the plugin will hook into the uploads and automatically sanitize any SVGs that you upload.

I’ll update this post when it’s on the WordPress directory but for now, here’s the download:

Click here to download

WordPress InnoDB Issues

I’ve been working with a lot of WordPress plugins recently and have come across a bug that had me stumped for a while, therefore, I thought it’d be worth sharing it here.

After installing and activating a plugin that created new database tables, I realised that the tables had not been installed. I contacted the plugin support who suggested re-installing WordPress. Reluctantly I did this but it didn’t help at all, I therefore decided I’d dig into the issue and see if I could track it down.

A bit of work and a few var_dump()‘s later I found that there as an error with the database creation SQL (below)

CREATE TABLE IF NOT EXISTS wp_domain_mapping (
    blog_id BIGINT NOT NULL,
    domain VARCHAR(255) NOT NULL,
    active TINYINT DEFAULT 1,
    PRIMARY KEY (id),
    KEY blog_id (blog_id, domain, active)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

I ran the query manually and realised it was returning the error Specified key was too long; max key length is 1000 bytes. I’d never seen this error before, so I dug into it a little more, this page informed me that InnoDB has a maximum key size of 1000 bytes, unless the innodb_large_prefix flag is set in MySQL in which case the maximum size is 3072 bytes.

That said, I found the following document where I could check the storage requirements of each field type. From this, I can tell that the BIGINT field, blog_id is 8 bytes, the TINYINT field, active is 1 byte and as UTF8 needs 3 bytes per character, the domain field is 255 * 3 bytes or 765 bytes. This gives us a total key length of 774 bytes.

It was then that I realised that I wasn’t using standard UTF8 but utf8mb4, which WordPress has set as it’s default character set as of 4.2. utf8mb4 requires 4 bytes per character and therefore the domain field calculation was wrong and was actually 255 * 4 bytes or 1,020 bytes in length. This is now an issue as our key is bigger than the size allowed by InnoDB hence the issue creating the tables.

Now as far as I can see, there is only one real way of getting around this and it’s the method WordPress has chosen, reducing the field length from 255 chars to something less, 247 in this case.

Now I know about this it shouldn’t be much of an issue, but I wonder how many plugin developers aren’t going to realise this has changed and are going to run into this. I foresee it being a major pain for a few months.

Anyway, onwards and upwards now!

Cheers for now!