Jun 06 2013

Using Apache as a PHP development server

I'm mostly a Python web developer, but PHP is the most popular runtime environment for web applications, and this makes it somewhat unavoidable.

When you're writing a web app in Python (or, really, most other languages), you test your code in a development server. It runs in the foreground in a Terminal window, and displays error messages rather than writing them to a log file, so you don't have to go digging around for them.

Since version 5.4, PHP can do this too. Unfortunately, if you're working on an app that uses a previous PHP version, or that is inextricably dependent on .htaccess files or some other Apache feature, this doesn't help you.

There are ways to run Apache-dependent PHP apps in development; on Mac OS X they usually involve adding virtual hosts to your global Apache instance, or installing MAMP. Neither of these give us the ability to conveniently start and stop our server with one command, or to have our logs conveniently appear as the output of that command. (MAMP also requires you to poke around in the settings of a GUI app to change your DocumentRoot every time you want to switch from one project to another.)

So, if we can't use a development server instead of Apache, let's make Apache act like a development server.

We'll use the Apache server that comes with OS X Mountain Lion, since the one from Homebrew inexplicably segfaults when you use PHP with it. But, we'll write our own configuration file for it. This is the bare minimum you need in an Apache config file for it to start up and serve static files:

Listen 8000
ErrorLog "|cat"
PidFile /full/path/to/a/directory/httpd.pid
LockFile /full/path/to/a/directory/accept.lock
DocumentRoot /full/path/to/your/project
ServerName localhost

Save that as httpd.conf. Some things to note here:

This will serve up static files, but that's about it; for other stuff, we need plugins.

Open the httpd.conf that comes with Mac OS X, located at /etc/apache2/httpd.conf. Copy the lines that start with LoadModule into your custom httpd.conf. You may want to go through each directive in your .htaccess files and determine which modules you need, you may want to see what your production server is running and install those, or you could just copy them all.

Then, comment out userdir_module if it's present (it was third from the bottom on my install). For some reason unknown to me, when this module is enabled at the same time as PHP, PHP somehow gets disabled and PHP scripts will be served up as static files instead of executed.

Last but not least, we'll add PHP itself. Mac OS X ships with PHP 5.3, but I want PHP 5.2, so I'll install it from Homebrew. (Note that if you don't already have MySQL and PostgreSQL installed, you'll have to either install them or remove the appropriate flags from brew install.)

$ brew tap homebrew/dupes
$ brew tap josegonzalez/php
$ brew install php52 --with-psql --with-mysql

Now, tell Apache about your PHP installation:

LoadModule php5_module /usr/local/opt/php52/libexec/apache2/libphp5.so

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
DirectoryIndex index.html index.php

Last but not least, run Apache in the foreground. (You'll notice that it really likes its absolute paths.)

$ httpd -f $PWD/httpd.conf -D FOREGROUND

You should now have a functioning Apache + PHP installation running right inside your terminal, separate from the OS's one.