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:
- We're serving up the site on port 8000, not 80, so we don't have to run Apache as root. If you have Web Sharing turned on in System Preferences, this also ensures we can fire up our Apache instance without interfering with the Web Sharing one.
- When the value for ErrorLog starts with a |, errors are piped out to the given command instead of written to a file. Since cat just copies standard input to standard output, we'll see errors in the terminal.
- All of the paths have to be absolute; relative paths won't work. For PidFile and LockFile, the directory must exist but the files must not.
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.