Article  |  Development

Wordpress and PHP on Rack

Reading time: Less than a minute

We work primarily in Ruby on Rails, but every once and a while a client will need us to fix a critical bug in an existing PHP/Wordpress app that is slated to be deprecated.

We use Pow on our development machines. This is great for developing Rails applications but it does't play so well with other stacks that require port 80 to run.

There are some instructions out on the web that show you how to use Apache in conjunction with Pow so that both apps can be served simultaneously. This seemed like a little too much overhead, so I started poking around for a solution.

Did you know that PHP comes with an embedded web server? Yup, it's built in as of PHP 5.4 and OS X Mavericks comes with it pre-installed. If you're looking for a newer version, you can install 5.5 using homebrew-php.

Now that we don't need Apache to run PHP, we'll need something to proxy requests back to our embedded server. For this, I used Rack.

I setup a simple Gemfile with the following gems:

gem 'rack'
gem 'rack-legacy'

Then it's time to create our rackup file. Create a file titled config.ru and add the following:

require 'rubygems'
require 'bundler'

Bundler.setup

require 'rack'
require 'rack-legacy'

use Rack::ShowExceptions
use Rack::Legacy::Index
use Rack::Legacy::Php
run Rack::File.new Dir.getwd

That's it! Place this file into the root of your PHP project and you should be able to call rackup from the terminal to start the Rack server. By default this will be at http://0.0.0.0:9292.

There is one caveat though. At this time, Rack Legacy, will only respond to requests if it thinks that it's a valid PHP file.

From the Rack Legacy library this is called before a request is proxied:

def valid? path
    return false unless path =~ /\.php/

    path = path[1..-1] if path =~ /^\//
    path = path.split('.php', 2)[0] + '.php'
    path = ::File.expand_path path, @public_dir
    ::File.file? path
end

In our case this wasn't working for us because of the way that pretty URLs were being handled by Wordpress. In order to get around that, I monkey-patched Rack Legacy to simply pass all requests back to PHP.

Here is what I added to the config.ru file to make this happen:

class Rack::Legacy::Php
    def valid? path
        return true
    end
end

With that change, the Wordpress site was working as expected.

Have a project that needs help?