Installing PHP 5.3, Apache2 and MySQL5 using MacPorts

I stopped using macports ages ago, if you aren’t using vagrant or something similar then you probably want to check out homebrew as an alternate mac package manager.

I’ve read a few posts on how to installed PHP on my mac using macports, but quite a few seem out of date or incomplete. I hope this is a guide on how I think it should be done from start to finish using easier to understand small steps.


28/08/09: Now works with Snow Leopard and this post has been updated reflect the latest variant changes to the PHP 5.3 install

03/09/09: Typo fixes and corrections from feedback

22/07/11: Updates for installing on OS-X 10.7 Lion

What? But my mac comes with PHP & Apache!

Well the first question should really be why use MacPorts instead of using the Apache/PHP that comes with OS-X. Basically the answer to that is that by default it’s not really setup for serious developer use, just the average end user who wants to play around with a script of hack together a small website. You could also use MAMP, but personally I don’t think it give me the level of control that I need as I try and develop with an environment as close to my production system that I can (i.e. a base unix environment). MAMP also hasn’t been updated for a while! Once you’re fully setup with MacPorts updating is a breeze and as the whole system has been compiled onto your machine in theory it should be a lot faster than a prebuilt universal binary.

Pre-Configure: Turn off the default web server

So the first thing you should do is to turn off Apache…

This is pretty simple, go to System Preferences, type Apache in it’s spotlight. It will highlight Sharing, but you just need to press return. Just make sure Web Sharing is disabled.

Setting up MacPorts

Install Xcode

Next you must make sure you’ve installed Apple’s Xcode Developer Tools (version 4.1 for Lion, version 3.1 or later for Leopard, or 2.4.1 or later for Tiger), found on the Mac App Store or at the Apple Developer Connection site or on your Mac OS X installation CDs/DVD. This basically installs a more complete unix developer base with compilers are other useful stuff needed for MacPorts.

Install MacPorts

After installing Xcode you can download and install MacPorts. The best way to install it is to use the DMG installer on the MacPorts site. On the other hand if you want to compile it from source then follow these steps:

Open up the Terminal

svn co
cd base
sudo make install

I recommend whichever way you install macports you should run this command to make sure everything is up to date:

sudo /opt/local/bin/port -v selfupdate

If nothing as gone wrong so far then you should have MacPorts fully setup. Only one more thing to do before installing PHP/MySQL and Apache

Update your system paths

Just so I don’t have to keep on typing /opt/local/bin all the time i’m going add that directory to my PATH. This information can be stored in your .profile which runs every time you start a new terminal. If you don’t have a .profile file use these steps to create one:

cd ~
echo 'export PATH=/opt/local/bin:/opt/local/sbin:$PATH' >> .profile

and that’s that. If you open a new terminal window (yes do that now) then those directories will be searched for terminal commands before the ones in the default path.

Setting up the LAMP stack

Enable SSL – if you want to!

Before installing PHP, i’m going to make sure that the version of curl installed is compiled with SSL enabled. If you don’t need or care about SSL then you can safely skip this step.

sudo port install curl +ssl

You should note that regardless if you run the command above first or one of the ones below then MacPorts will download a whole bunch or ports that are required to install that port or one of its dependencies. Also these commands may take sometime, so give it a while or go make a cup a tea.

Install MySQL

This one is fairly simple, well kind of…

sudo port install mysql5-server

Note: a lot of blogs recommend installing just the mysql5 port, but if you want the option to have MySQL start automatically at startup you’ll want to install the server. The mysql5-server port installs the mysql5 port anyway, so you can’t lose!

If you want to run MySQL at startup then run this command after the port finishes installing

sudo port load mysql5-server

Finally to make sure that the database if fully setup you must run this command (before starting up any mysql process!)

sudo -u _mysql mysql_install_db5

And make sure you pay attention to its instructions! Personally I didn’t do anything here as this is a development setup for me, so I prefer to keep my settings loose. Although if you want MySQL commands in your terminals path (like port) then run these commands and start a new terminal:

cd ~
echo 'export PATH=/opt/local/lib/mysql5/bin:$PATH' >> .profile

Create /opt/local/etc/mysql5/my.cnf, add the following to it and save

[mysqld_safe] socket = /tmp/mysql.sock

Also to remain compatible with other programs that may have been coded to look for the socket file in its original location then add this symbolic link:

sudo ln -s /tmp/mysql.sock /opt/local/var/run/mysql5/mysqld.sock

Install PHP & Apache

Ok we’re finally installing PHP with MySQL support and Apache (FastCGI is just being installed separately for use with some debugging and profiling tools).

sudo port install php5 +apache2 +pear +fastcgi php5-mysql +mysqlnd

Like MySQL if you want Apache to start automatically when you start your computer then run this command after the port installs (as shown while the ports are installing)

sudo port load apache2

Configure PHP

To customize php, copy /opt/local/etc/php5/php.ini-development (if this is a development server) or /opt/local/etc/php5/php.ini-production (if this is a production server) to /opt/local/etc/php5/php.ini and then make changes (see below).

i.e. for development:

cd /opt/local/etc/php5/
sudo cp php.ini-development php.ini

i.e. for production:

cd /opt/local/etc/php5/
sudo cp php.ini-production php.ini

To customize php edit (using your favourite editor) /opt/local/etc/php5/php.ini to configure it properly, make sure you set the correct timezone (for myself it’s this):

date.timezone = Europe/London

Configure Apache

If this is your first install, you need to activate PHP in your web server.To enable PHP in Apache, run

cd /opt/local/apache2/modules
sudo /opt/local/apache2/bin/apxs -a -e -n "php5"

Open /opt/local/apache2/conf/httpd.conf in your favourite text editor (it’s vi for me, but feel free to use pico, emacs or whatever!).

sudo vi /opt/local/apache2/conf/httpd.conf

If you want to change the default MacPorts Apache document root to match default Apple’s Apache (personally I didn’t, but I found this information on another blog – so it might be useful to some), change:

DocumentRoot "/opt/local/apache2/htdocs"


DocumentRoot "/Library/WebServer/Documents"

If you changed the DocumentRoot, change the Directory directive from:

<Directory "/opt/local/apache2/htdocs">


<Directory "/Library/WebServer/Documents">

For PHP to work correctly you must add index.php to the dir_module directive:

<IfModule dir_module>
    DirectoryIndex index.html index.php

Add a new mimetype so that Apache will direct files ending in .php to the PHP module for processing. Add the following within the <IfModule mime_module> block. Without this, all you’ll see is the text of your PHP scripts

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

And finally, to enable user directories, uncomment:

Include conf/extra/httpd-userdir.conf

But if you are going to use virtual hosts (as described below) then uncomment this line in addition to (or instead of) the line above:

Include conf/extra/httpd-vhosts.conf

Save and close the httpd.conf file.

Advanced Post-Configuration

Configure Apache Virtual Hosts

Now unless you just want to access your new web server using http://localhost you might want to set up some virtual hosts for Apache. I personally only need one virtual host atm i.e. Virtual hosts need to be configured in two places, the hosts file (/etc/hosts) and the Apache virtual hosts file (/opt/local/apache2/conf/extra/httpd-vhosts.conf).

Firstly add this line to /etc/hosts after the localhost has been defined i.e.    localhost

Then you must edit the virtual hosts file /opt/local/apache2/conf/extra/httpd-vhosts.conf and add this configuration

<VirtualHost *:80>
    DocumentRoot "/opt/local/apache2/vhosts/"
    ErrorLog "logs/"
    CustomLog "logs/" common

The document root can be anything you want as long as apache has permissions to read that directory i.e. in this case you can:

sudo mkdir -p /opt/local/apache2/vhosts/
cd /opt/local/apache2/vhosts/
sudo chmod -R 755

You can do this process for as many virtual hosts as you want. Also I personally keep all my websites stored in my user directory – yes bad on a server, but this is my personal development machine. Finally don’t forget to comment out or remove the example vhosts from http-vhost.conf or you’ll get warnings while starting up Apache, they are harmless to leave in, but it’s probably for the best to remove any potential errors

Installing extra PHP modules

There are plenty of extra PHP modules available from MacPorts, you can get a list of them by using this command. Although you won’t need any of the MySQL ones as you’ve already compiled it into PHP.

port search php5-

Here is the list of PHP5 ports I installed

sudo port install php5-openssl php5-curl php5-gd php5-iconv php5-http php5-mcrypt php5-xdebug

Updating MacPorts

MacPorts is simple to update, every few weeks I just run the command below to check for any outdated ports (i’ll also update this post with any changes to this process I discover)

sudo port outdated

to update all installed ports to the latests and greatest

sudo port upgrade outdated

That’s It

Now if you restart your computer and add code into the document root of your website (in this case then you should have a fully working web server with PHP and MySQL. Ok it wasn’t easy, but for me it’s the best solution over the longer term


Just an update from my previous post. I’ve updated my little mashup to be a lot faster than it was and I still have a few optimizations in mind to speed it up even more. Also the site now handles any UK location (well the ones which google maps can geocode into a longitude and latitude) and finally I gave it a humorous name (well I found it funny).

Here’s the link again: UpYourAlley give the site a few seconds to load the markers and the same applies when you click on any marker.

Still there are a few little bugs and niggles that I need to sort out:

  • If more than one venue is at the same location then only one is currently shown.
  • The marker manager code I have isn’t as efficient and smart as I would like especially when scrolling around the map.
  • I would like to be able to filter (on a search) events by category i.e. movies, arts, gigs etc…, but that should be trivial.
  • More user feedback when loading data and handling failure when the users location cannot be geocoded.
  • Plus more, more and then some more…

For those who care about why it’s faster now…. I previously generating the data set completely in PHP on the server-side, but as each api request was made in series to PA the time taken to gather just the venue data took around 15 seconds and when factoring in the events data for each venue this grew to minutes. So when I rewrote the site (waiting for Top Gear at 9pm on sunday night – I thought it started at 8pm!) I set all the requests* to be sent asynchronous from the client using jquery and surprise surprise everything ran faster, although more bandwidth is used and more requests are made in total.

* The requests are still proxied through PHP to PA as I strip out and sort some data as well as hiding the API key that I use.

What’s happening near Balham

I’ve been allowed to play around with a new web service developed by some former colleagues at the Press Association (PA). The service gives you some access to PA’s entertainment listings database (think guardian guide, listings section of the Metro and most other papers etc. it all comes from the same source).

The data is organized into venues (your local arts center), titles (a movie on nationwide release) and events (a title and venue combination at a specific start/end times). Or for the more data minded venues can have zero to many titles, titles can have zero to many venues, events have an unique combination of one title, one venue and a date & time.

Anyway to quickly try out the new service I knocked up a quick mashup of what events are on in my local area each day. Firstly this mashup is massively slow as my host doesn’t have memcached installed for personal use *cough* Dreamhost *cough*. This is also partially due to the structure of the web service as I have to make a lot of requests to generate this mashup, but I’ll keep that feedback confidential for now as the web service isn’t complete nor open to external use yet.

Anyway here’s the link: (please give it a minute or two to load the data – yes really).

Once I get some time to play with it some more

  • I’ll open up the map to allow users to select their own local area
  • Have some dynamic marker loading on scrolling
  • Allow options to select which days to look for events (apart from today)
  • Filter by event types (only gigs, cinemas, comedy or combinations thereof).
  • Show more venue information
  • Optionally show more information about the event or title
  • Refactor, refactor, refactor…
For those interested the site uses jquery & the jmaps plugin to generate the map and gather data from a simple PHP proxy script which collates the data from PA into a JSON.
I can’t overstate how big a step forward this is for PA and hopefully we’ll see more of this from them in the future.
UPDATE: As always the moment you publish something is exactly the same moment you figure out how to fix the problem your having. I should be able to massively speed up the site, but I’m not going to do that today.

Just another javascript flickr mashup…


Over the last few weeks i’ve moved over all my pictures from my php gallery to flickr, so now I really need to replace my hosted gallery with something better than a link to my flickr account. My solution to this was to create (what I think is) a nice little mashup of flickr hosted based pictures and a javascript visulisation of them. Rather than use one of the many flickr mashup’s out there I decided it was more fun to wrote my own…Simply i’ve taken 36 square thumbnails arranged in a 9×4 grid from flickr and used a combination of prototype, cube (with some modifications), lightbox2 with some javascript glue of my own to bind them together.

What does it do…

Well it’s easier to see it, but every second or two a randomly selected thumbnail in the 9×4 grid will rotate to a new picture from flickr and then this repeats forever. You can also click on any of the thumbnails in the grid to hightlight a picture and eventually i’ll provide a link to where that photo is hosted on flickr, once a figure out a better way to do it than to put the link into the title.

How’s it work…

Well i’m using a php script on my server to get a selection of photo details using phpFlickr; I decided to get 72 photo objects ever time I accessed to script, but on the initial load I display the first 36 onto the page. I used prototype to handle the Ajax request and json parsing, I guess I could I done this without prototype, but I couldn’t be bothered and it would have taken longer and lightbox2 requires it anyway! Then using a javascript image cube animation library I found this will animate a image rotation to a new picture from the remaining 36 pictures. Although I did have to modify the cube library a bit to use absolute positioning and setting some divs to be inline apart from the first thumbnail of the row. Once the page has runout of pictures from the initial server script load a new call is made to that script for another page of 72 picture objects from flickr … and so on … and so on … I also used lightbox2 to load up a larger version of the square thumbnail when you click on the thumbnail.

You didn’t take those pictures…

At the moment I’m just using the interesting pictures from flickr (they look better than mine), but once I fix the odd bug or few I’ll replace my hosted gallery to a nicer version of this mashup using my own pictures. Phew! PS Thanks firebug!

Simple Storage Service (You’ve Come a Long Way, Baby)

It’s taking a few weeks of cooking, but my Simple Storage Service is ready to come out of the oven to be eaten (and possibly spat out) by the world at large. Now there are still a couple of things on my TODO list, but nothing massive. Basically URL authentication of requests (needs some thought), postObject (I need to read the docs), virtual hosting of buckets (a lot of thought) and some tiny changes and bugs that i’ll fix over the next few days. So what has changed since my last post:

  • Anonymous requests can now be made where permission to do so has been set.
  • Authenticated/Alluser groups and ACL get and sets have been implemented.
  • All REST calls have been implemented (except postObject)*
  • Exception handling matches the S3 documentation (with some guess work)
  • The REST layer was completely rewritten using test driven development
  • phpDocumentator comments are being added to the code, so docs can be generated
  • I’ve created a web form to help you create new users to the service

So what’s next …. ? I guess I’ll polish what’s been completed so far and add some documentation to make it simpler to deploy. And as i’m off Snow boarding from Saturday i’ll wait to see what sort of feedback I get before getting started on the SOAP section which should be easier now that I’ve got a good testing setup + looking for a new job as i’ll be leaving mine soon! I’ve also found that the most popular php client for S3 (from a google search) is missing some useful functionality, so i’m pondering re-writing it and making several optimizations so it can stream downloads from S3 etc etc…

The best use for this software, apart from academic curiosity and mocking is probably a failover/backup service incase S3 goes down (which it has done). This would work best if you are CNAME record to map to as I believe that as this is under your DNS control it is fairly trivial to map it to another host.

Other than that I’ll write a blog on how to set it up using xampp on windows and macports on a mac (when I MacBook Pro arrives)…

You can checkout the latest code from here:

UPDATE: svn is broke since I moved to slicehost, you can download the code here:

* As this service hasn’t been developed to work to meet Amazon’s data consistency model I implemented getBucketLocation, but essentially it does nothing. Although in theory I could use MySQL clustering to implement this I’m not going to unless someone wants to pay me and I also don’t have a global server network to play with 😉

Aspects and PHP

phpAspects is a project to bring Aspect-oriented programming (AOP) to PHP. If you don’t know much about aspects then to state it very simply aspects is a way to separate concerns such as logging and dependencies like database handling to produce more manageable and maintainable code, but the wikipedia article on aspects can describe this better than I can!

Now this project isn’t really mature at the moment i.e. it’s alpha version 0.10 which means it’s very likely to change alot before it becomes final which is the main reason I’ve decided not to use it from my SimpleStorageService project – although I’m really tempted to play around with it anyway; The other reason why I’m not going to use it is because i’d have to add another PECL dependency to the project (on top of PDO) which is Parse_Tree (another alpha dependency… Hmmm!). Then again over the last few days I’ve come to believe if you want to write a REST interface on a LAMP style stack you’re going to need to be able to have server level access to configure Apache to allow PUT & DELETE HTTP verbs (editing httpd.conf), although I’m hoping to find a higher level solution to that problem for easier deployment.

But I do recommend that it’s a project you should keep your eye on as sooner or later you’re going to want to use Aspects to keep your code clean and simple. Once it is a bit more mature I will be using it in some or my more work related projects where I’ll have more control of which extensions are compiled into PHP.

One reason not to use a email address as an username

I’m helping out a friend at the moment to include a forum into a charity site. The site is used by teachers and students as a educational resource and some of the resources are protected by your typical authentication system which uses the users email address as a username and a password of their choosing. Now none of this would normally set of any alarm bells, but adding a forum to this site brought a question.

 A typical forum uses a unique friendly name to identify users without exposing any contact information. If the only unique user identifier you have is a email address and you for very obvious reasons you don’t want teacher and students email addresses exposed then how do you resolve this?

In this case a solution was achievable although with caveats which I’m not going to go into right now, but in future when I (or you) design an authentication system it might do you good to at least consider how your user identifier is going to be used.

Before anyone says use OpenID I just don’t think it really would work in forums (yet); Although I know that you can have a nickname in OpenID it’s just too clunky a system at the moment to create a new persona for a new site for the average user (if your default nickname is already in use) i.e. it doesn’t pass my ‘Can my mum understand this?’ test!

Do I have a better solution – hell no, but i’m sure smarty people than me are thinking about it!

UPDATE: I found a excellent blog which articulates some of my concerns about OpenID

Simple Storage Service – Very Alpha Release

So after reading about the unscheduled downtime of Amazon S3 yesterday I thought that I should probably release what I’ve done so far. Although most of the work I’ve done has been focused on the storage layer and writing many many tests for it. So last night I spent a few hours hacking in functionality into what will be the REST layer of the service mostly from a PHP S3 Client to provide a very basic service to show what I’ve been doing – mostly handcrafted responses; although I’m probably going to the the pecl http extension to handle most of this in the future

This isn’t really up-to what I’d call alpha ‘quality’ in any respect, but it’s just a sneak peak with many many cavets i.e.

Anonymous authentication doesn’t work at all (you need an authenticated user for all method calls)

Only putBucket, deleteBucket, putObject, getObject, deleteObject have been partially implemented, although most methods are implemented at the storage layer.

Many many things need to be re-factored

Exception handling isn’t fully implemented yet

The REST layer has no tests and the SOAP layer hasn’t been started yet

You need the (PECL) PDO MySQL extension added to PHP (and probably some other PEAR libraries like Crypt/HMAC)

No documentation yet, but I’m willing to help with any questions

You need to be able to edit the httpd.conf for apache to enable PUT and DELETE http verbs*

If your running PHP as CGI then you may need to modify my .htaccess (well maybe?)

You need to create your own user using createUser in the storage class (but I’ll add a script into the subversion to help with this)

Security hasn’t been tested and the code is not optimized in any way

Plus some other stuff that I may have forgotten because I’m tired

You may have got the impression that I’m not entirely satisfied with this code yet and you’d be right. I’m only releasing this as *some* people *may* find it interesting. And one final thing, I don’t have a Amazon S3 account, I’ve basically cobbled this together from the documentation (which can be inconsistent), because I read the T&C’s and I wasn’t sure if Amazon would sue me if I agreed to them, so I didn’t!

Also you’ll need to create a mysql database, but the database details are hardcoded into the src/s3/lib/storage.php file and test/AbstractTest.php for unit tests.

So … blah, blah … it might not work … blah, blah … give me a break and i’ll help you ….. blah, blah …. I won’t be able to do any more work on this for one week before I start again … so here is the SVN URL ….

On the positive side of things, when I do get time next week to continue working on this project the hardest parts of the project have been thought about or have already completed, so implemented the REST and SOAP layers shouldn’t take along as I did implementing the storage layer.

* You need to modify your httpd.conf to allow PUT and DELETE http verbs by including these commands in your htdocs <DIRECTORY> tag (Apache doesn’t allow PUT or DELETE http verbs by default for sensible security reasons)

Script PUT /workspace/s3server/src/index.php

Script DELETE /workspace/s3server/src/index.php

Where the index.php matches where you (relative to your htdocs path) checked out the code.

Agile and PHP

So since my last post I’ve actually started to write my SimpleStorageService project and as I’m an agile developer I decided to write the project with the agile skills I’ve picked up over the last few years with Java, .net, scrum-master training et al and check out how easy it actually is to ‘do agile’ with PHP.

So…. where should I begin….

Unit Testing (Test Driven Development):

Firstly PHP has had unit testing for quite some time with PHPUnit; this is something which after using unit testing in Java and C# was actually quite straight forward and although there are other testing frameworks like SimpleTest I decided to go with PHPUnit as it seems more comprehensive; Although I found that SimpleTest has a better mocking implementation than PHPUnit, but for now I’m sticking with PHPUnit.

Also PHPUnit can integrate with Selenium and has a partial implementation of DbUnit, but that’s not complete yet – hopefully this will be complete by PHPUnit 4

Continuous Integration:

Now I didn’t think PHP had anything like this, so when I was looking into testing I found the phpUnderControl project which literally knocked my coding socks off as it’s a PHP wrapper for cruiseControl, but with a cool interface and extra PHP goodies on project code metrics, a Java like checkStyle which defaults to the PEAR coding standard and generating phpDoc as well as the normal cruiseControl stuff.

I was so impressed by this project that at the time (early January) I set it up on my macmini although I did have to use macports to replace the crippled default build of PHP that is bundled with OS X (please fix this Apple!). I initially installed version 0.20 of phpUnderControl, but I’m currently upgrading my install to the recently released version 0.30 which has a neat javascript metrics view – which is nice

Finally phpUnderControl neatly integrates with PHPUnit, which another reason why I’m using this and the project is now hosted alongside PHPUnit, so I hope to see more integration between the projects in the future.

Integrated Development Environment:

Allow this is by all means not needed to practise Agile, but a good IDE helps you write better code faster. I used to use DreamWeaver for all my PHP web development work, but as my SimpleStorageService is by definition a service project I didn’t need any HTML editing functionality. Anyway here was my IDE shortlist:

Ignoring DreamWeaver and TextPad as being out of date and inappropriate for the project I began with Eclipse (with PDT), but I quickly found several problems with this mainly SVN integration amongst other things. Then I gave Aptana a go which was beta at the time and did fix my SVN issues, but in the final version this was removed from the free edition (grrr!). So just when I thought that PHP didn’t have a good IDE literally stumbledupon Zend Studio Neon which ticked nearly every box I wanted from a IDE for PHP … PHPUnit, phpDoc, SVN, code coverage, code formatting, real time error checking, intellisense and much much more. The downsides are a bug where it doesn’t understand the PDO class when unit-testing (well it is beta!) and the final version isn’t free, so I’m using a time trial version which runs out in just over two weeks. Anyone want to buy me a copy 😉

Source Control:

It still surprises me how many people don’t use or even understand the point of source-control, but I’ve been a big user for many years. Firstly with CVS and then once Subversion (SVN) was more stable I moved to that and didn’t look back. I know there are many other choices here, but as SVN is integrated into phpUnderControl and Zend Studio it was simply a no brainer. My DreamHost account includes SVN so all my code can be committed ‘off site’ and I can create an abstraction between my IDE and continuous integration environment.


The state of Agile in PHP is good and much much better than it was even six months ago. I think once PHPUnit 4 is released, phpUnderControl reaches stablity and Eclipse with PDT catches up with Zend Studio (add unit testing, svn projects) then Agile in PHP should be excellent and easy to accomplish. One thing I haven’t looked at is if PHP has any good scrum management products (but I guess this doesn’t necessarily have to be in PHP).