MongoDB on OS X with the stock PHP installation

5th June 2010

MongoDB was mentioned a few times at tek and I said that I wanted to have a look at.

Travis' article, MongoDB: A first look, came out a few days ago and piqued my interest further. Then Matthew sent me some source code that requires it. The stage was set for getting MongoDB working on my Mac.

MongoDB

I use homebrew as a package manager for installing open source bits and bobs like couchdb, git, and hg. Installing MongoDB was simply a case of:

brew install mongodb

Once, installed there's a convenient LaunchAgent plist supplied so that mongodb starts with the computer:

cp /usr/local/Cellar/mongodb/1.4.3-x86_64/org.mongodb.mongod.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/org.mongodb.mongod.plist

And at this point, MongoDB is installed on your Mac and Travis' article and the tutorial work!

The Mongo PHP extension

If you've been following along here for a while, then you'll know that I use the stock PHP that comes with Mac OS X. I've been very happy with it so far and installed Xdebug was easy enough using pecl, so I was hopeful that the mongo extension would be equally simple.

Turns out that it is!

pecl install mongo

Compiles the extension with no problems.

To add it to your PHP install, edit php.ini and add:

extension=mongo.so

A quick sudo apachectl restart and phpinfo() shows this:

MongoDB in phpinfo

All done! You can now get at MongoDB from your PHP scripts.

Sending a file to IE using SSL

23rd March 2010

I keep coming across this one, so I'm noting it here so I can find it again.

Internet Explorer doesn't like certain headers related to caching when you send it a file from an SSL site. The Microsoft knowledge base article, Internet Explorer is unable to open Office documents from an SSL Web site explains the problem quite well:

When you attempt to open or download a Microsoft Office document (.doc file, .xls file, .ppt file, and so on) from a secure Web site in Internet Explorer, you may receive one of the following error messages, even though the document is available and downloaded from the server

It turns out that the problem is directly due to sending these headers:


Pragmano-cache  
Cache-controlno-cache,max-age=0,must-revalidate

So, make sure you don't!

Incidentally, IE6 also gets upset if you set max-age to 0 and attachment to inline, so don't do that either!

Redirecting email whilst developing

15th January 2010

One common problem whilst developing is that you don't want to send emails out to the client (or their clients!). Ideally, we want to alter our development environment so that this doesn't happen, but still allows us to test the contents of emails that are sent by our web applications.

Windows

On Windows, the mail() function uses SMTP over port 25. Unless you've changed your php.ini file, then it will try to connect to localhost in order to send an email. On Windows VM, I use Fakemail. This is an SMTP mail server written in perl (or python) that store emails as files into a given directory. When your web application sends an email, you check in the directory and look at the files created. One top tip: alter the script to give each file a .txt extension. Then you can double click :)

Fakemail is also very useful in Linux/Mac if you are using the SMTP transport mail in Zend_Mail or Swiftmailer or whatever.

Linux / OS X

On the *nix based systems, mail() sends email using an application on the system called sendmail (or any number of compatible alternatives). By default it will call the sendmail binary, however you can change this in your php.ini with the sendmail_path setting.

I set my development boxes like this:


sendmail_path = /usr/local/bin/trapmail

Now, mail() will call my trapmail script. This script is trivial:


formail -R cc X-original-cc 
  -R to X-original-to 
  -R bcc X-original-bcc 
  --A"To: rob@akrabat.com" 
| /usr/sbin/sendmail --i

This script causes all emails to be redirect to my email address with the original to, cc and bcc fields renamed in the headers, so they can be checked!. I like this solution even better than Fakemail as it's easier to see exactly what the mail looks like in a mail client, especially for HTML format.

I just wish I had thought of this script myself! However Sean Coates came up with the idea in 2005 and I've been using it every since.

PHP Advent 2009: On deployment

6th December 2009

This year I was asked to write an article for PHP Advent 2009 an it's now been published!

Automate your Deployment is a look at how to automate the process of deploying your application to the web server. At my company we started automating our deployment systems just over a year and the number of issues we have around deployment of new code to a website has dropped considerably and is no longer a stressful event.

If you aren't currently using an automated deployment script, I can't recommend highly enough that you set yourself a New Year's resolution to investigate the options and implement a system for yourself.

PHPNW 09 Conference

17th October 2009

The PHPNW 09 Conference took place last Saturday and I've finally found time to write up my thoughts on it.

I went up on Friday in order to meet up with the speakers for dinner and also to go to the pre-conference social at the Lass O'Gowrie.

The PHPNW09 speakers' dinner

The conference was kicked off with an excellent keynote by Kevlin Henney on uncertainty. The main point I took away was that the attitude of "any decision is better than no decision" is completely wrong for software development. It is much better to delay a decision until you have enough information to make it.

There were two tracks for the rest of the day. I listened to Lorna Mitchell talk about development best practices in the context of The Joel Test. This was interesting and I was pleased to note that whilst my company doesn't have a score of 12, we have talked about all the items internally.

I then listened to Rowan Merewood of Plusnet who talked about introducing new tools and development practices into a team environment. One key point he made was that it is important to have a "champion" on the team to push for the new tool/practice and I couldn't agree more. Everything that has "stuck" in our team has been because someone in the team really cares about it.

The provided lunch was very good and a noticeable step-up from last year's sandwiches :) I also noticed that the WiFi seemed to work well too.

Dinner was excellent

After lunch, it was my turn to talk about project management. Whilst not something that most of the delegates would do in their day to day work, I hope that they learnt a little of how the project management process works. Maybe, even picking up a few ideas on how they can help out with ensuring a project is a success. I can say with certainty that the most successful projects that I've managed have most closely followed what I talked about. The ones that go wrong are the ones where we take shortcuts which then come back and bite us!

After my talk, Derick Rethans talked about how useful Xdebug is and how to use its many features.

I bowed out of the talks at this point and spent the next couple of hours talking to people and learning interesting stuff on a more personal level.

The closing session included a segment by Microsoft where they talked about Expression. I found this quite frustrating as I couldn't help but think that they could have used the time better to tell us about how great PHP is on Windows now. They should be shouting about the fact that Windows is now a first class server platform for PHP applications at every opportunity. Not telling us about a wire-framing tool. What do I know though?!

After the conference, Sun Microsystems sponsored an open bar which was very much appreciated.

Free drinks after the conference

On Sunday, a set of informal sessions took place at MOSI. I overslept and managed to miss the first couple of hours and then spent the rest of the time talking to people rather than listening to sessions. It's a habit I have! I also looked around the museum and could quite easily go back and spend a day or two there.

PHPNW09: The day after at MOSI

All in all, PHPNW 09 was a fantastic conference.

Setting up PHP & MySQL on OS X 10.6 Snow Leopard

5th October 2009

(Updated 1st May 2010)

With OS X 10.6, Apple ships PHP 5.3 with PEAR, GD and PDO_MYSQL out of the box. Also, everything is now 64bit. This means that the entire effort required to get a working PHP dev environment for my work is now much easier.

/usr/local

Ensure that the following directories exist:

sudo mkdir /usr/local/include
sudo mkdir /usr/local/bin
sudo mkdir /usr/local/lib
sudo mkdir -p /usr/local/man/man1

MySQL

  1. Download the 64bit DMG version of MySQL 5.0.x for OS X 10.6 from mysql.com and install the pkg, the startup item and the pref pane.
  2. Add /usr/local/mysql/bin to the path: vim ~/.bash_profile and add:
    export PATH=~/bin:/usr/local/bin:/usr/local/mysql/bin:$PATH
    export EDITOR=vim
    

    at top of file. (Note that we set EDITOR whilst we are here so that svn is happy!)

  3. Set up MySQL root password:
    mysqladmin -u root password {new-password}
    mysqladmin -u root -p{new-password} -h localhost password {new-password}
    mysqladmin -u root -p reload
    

    Clear the history file by typing history -c so that {new-password} isn't in plain text on the disk.

Apache

  1. cd /etc/apache2
  2. sudo vim httpd.conf
  3. Find #LoadModule php5_module libexec/apache2/libphp5.so and remove the leading #
  4. Find AllowOverride None within the <Directory "/Library/WebServer/Documents">section and change toAllowOverride All so that .htaccess files will work.
  5. Restart Apache: sudo apachectl restart
  6. Open Finder and navigate to /Library/WebServer/Documents/
  7. Create a new folder called "orig" and place all files currently in the Documents folder into it.
  8. Create a new file called info.php with <?php phpinfo(); inside it.
  9. Use Safari to navigate to http://localhost/info.php and check that the PHP version is displayed (5.3.0 at the time of writing).

php.ini

  1. cd /etc
  2. sudo cp php.ini.default php.ini
  3. sudo chmod ug+w php.ini
  4. sudo chgrp admin php.ini
  5. vim php.ini (assuming your user is a member of the admin group) and change settings appropriately. Change:
    error_reporting  =  E_ALL | E_STRICT
    display_errors = On
    html_errors = On
    extension_dir = "/usr/lib/php/extensions/no-debug-non-zts-20090626"
    

    (I like to see my xdebug errors in bright orange!)
    Also, change all instances of /var/mysql/mysql.sock to /tmp/mysql.sock

Xdebug

Can't have a PHP development environment without xdebug!

  1. sudo pecl channel-update pecl.php.net
  2. sudo pear channel-update pear.php.net
  3. sudo pecl install xdebug
  4. Edit /etc/php.ini and add
    zend_extension="/usr/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so"

    after the other extension lines.

  5. Restart apache: sudo apachectl restart and check in the phpinfo that xdebug is now loaded.

PHPUnit

  1. sudo pear upgrade-all
  2. sudo pear channel-discover pear.phpunit.de
  3. sudo pear install phpunit/PHPUnit

It all works on this machine, anyway :)

Changing OS X Terminal colours when ssh'ing into a server

2nd October 2009

I recently discovered that iTerm has bookmarks so you can set up a bookmark to ssh into a server and change the colours of the window. This makes it easy to remember which terminal window is for which server.

Thinking about it, I wondered if you could change the colours of the standard OS X Terminal via AppleScript. Inpired by Red Sweater's Random Color Terminal post, I wrote some code to automatically change the Terminal colour whenever I ssh into a known server.

As I know PHP and PHP is installed on OS X, I used that :)

The key to controlling AppleScript via PHP is the osascript command line application. The code I need specifically is:


system("osascript -e 'tell application \"Terminal\"
            set targetWindow to window 1
            set background color of targetWindow to {" $bgColour "}
            set cursor color of targetWindow to {" $fgColour "}
            set normal text color of targetWindow to {" $fgColour "}
            set bold text color of targetWindow to {" $fgColour "}
        end tell' ");

where $bgColour and $fgColour are comma separated strings containing three numbers between 0 and 65535 as AppleScript colours are 16 bit.

We start by getting a command line solution where we can type:
termcolour.php white
or
termcolour.php 00ff00
or
termcolour.php 255 0 0

and have the background colour of the Terminal change to the colour we have asked for.

TerminalColour class

Firstly we need a class that can change the colour of the Terminal window for us and also translate colours from 8bit RGB to 16bit RGB. As it is also useful to be able to specify colours by name, eg. "white", we'll add a lookup system too. I store this in /usr/local/bin.

This class is quite long, so this is a snippet:

<?php
class TerminalColour
{
    protected $_colour = array('255','255','255');
    
    /**
     * List of colours
     */
    protected $_colours = array(
        'white' => 'ffffff',
        'black' => '000000',
        // etc
    );
    

    /**
     * Set the colour of the topmost Terminal window using AppleScript
     *
     * $bgColour may be either an array of red, green, blue (8 bit) or a 
     * hex string or a string that matches an entry in the _colours lookup 
     * list.
     *
     * If $fgColour is null, then automatically use either black or
     * white based on brightness of $bgColour.
     *
     * @param array|string $bgColour
     * @param array|string $fgColour
     * @return array
     */
    function setTerminalColour($bgColour=null$fgColour=null) 
    {
        if(!is_null($bgColour)) {
            $this->setColour($bgColour);
        }
        $bgColour $this->getColour();
        
        
        // convert from 8 bit colour numbers to 16 bit ones
        $bgColour $this->convertTo16bit($bgColour);
            
        if($fgColour === null) {
            $fgColour $this->getFgColour($bgColour);
        } else {
        }
        
        $bgColour implode(','$bgColour);
        $fgColour implode(','$fgColour);
    
        system("osascript -e 'tell application \"Terminal\"
            set targetWindow to window 1
            set background color of targetWindow to {" $bgColour "}
            set cursor color of targetWindow to {" $fgColour "}
            set normal text color of targetWindow to {" $fgColour "}
            set bold text color of targetWindow to {" $fgColour "}
        end tell' ");
    }
}

As you can see, there's a variety of helper methods that I've not show here. setColour() is the where we map from the types of input that the user will provide to an array. Other that that, it's fairly self-explanatory.

Change colour from the command line

Now we need a script that uses our class. termcolours.php, that I can execute from the command line to change any given Terminal window to a new background colour.

termcolour.php is stored in /usr/local/bin and has execute permissions set using chmod a+x termcolour.php from the command line:

#!/usr/bin/php
<?php
include dirname(__FILE__) . '/TerminalColour.php';

process($argc$argv);
exit;

function process($argc$argv)
{
    if($argc == 1) {
        echo <<<EOT
TerminalColour: Set the background colour of a Terminal.app window 
USAGE: 
    1. termcolour.php {r} {g} {b} 
        ({r}, {g}, {b} are between 0 and 255)
    2. termcolour.php {hexvalue}
        ({hexvalue} assumed to be from 000 to fff or 00000 to ffffff)

EOT;
        exit;
    }
    
    $tc = new TerminalColour();
    if($argc == 4) {
        // called with three arguments - treat as rgb values (0-255)
        array_shift($argv); // remove name of script
        $tc->setTerminalColour($argv);
    }
    
    if($argc == 2) {
        // called with one argument - either a lookup or a hex value
        $tc->setTerminalColour($argv[1]);
    }
}

Again, not complicated. we check number of arguments to the script and if there are none, we display a help message. If there are exactly 1 or 3, then we call TerminalColour::setTerminalColour() appropriately.

Hooking into SSH

Lastly we hook into ssh and change the colour based on the server name.

To do this, I've used a simple shell script and modified termcolours.php to add some additional colour look up entries.

/usr/local/bin/sshcolours.sh:
/usr/local/bin/termcolour.php $@
/usr/bin/ssh $@
/usr/local/bin/termcolour.php white

termcolour.php


//...
    
    $tc = new TerminalColour();

    // add colours for servers
    $colourLookup $tc->getLookupColours();
    $serverColours = array(
        'server1' => $colourLookup['darkblue'],
        'server2' => $colourLookup['red'],
        'server3' => 'C4DFC3',
    );
    $tc->addToLookupColours($serverColours);

    if($argc == 4) {
//...

(not a large change!)

finally, we add an alias to ~/.bash_profile:


alias s=sshcolours.sh

That's it! I can now type:

	s server1

and Terminal's background colour turns blue and I'm ssh'd into server 1.

Sometimes I just type termcolour.php darkred to remind myself that this terminal window is doing something long-running and not to accidentally close it...

This is a zip file of the relevant files.

A new blog from someone new to PHP

13th September 2009

I met Chris when he was temping for a client of mine doing data entry into an e-commerce system we were writing. Recently he contacted me to let me know that he has now started learning PHP and is starting to develop a career in web development with PHP. I was quite impressed that he had even managed to land himself some freelance work and had a client happy enough to pay him!

He asked me for some advice and I provided some information on the sorts of things he need to learn about and some ideas on where to find communities that will help.

I had recently read Cal Evans' PHP and Community post, which contains this gem:

Until all 4.6 million PHP developers are active in the community, there is always a seat at the table. If you are a PHP developer - junior level, architect level or just a weekend warrior - I urge you to get involved.

Start a blog and write about what you have learned. Trust me, if you put up something that isn’t accurate, someone will come along and correct you. That’s a win for everyone.

As a result, I also advised him to start a blog so that he can document what he now knows to the benefit of us all and also allow potential employers the opportunity to understand his skills much better than a mere CV can show.

He's taken this advice and http://jibbles.co.uk/ has been born. It turns out that Chris is a very good writer - much better than I was when I started (and probably better than I am now too)! If you are interested in watching a new coder develop into a better coder, then it may be worth keeping an eye on his blog. You could also comment periodically when he needs a pointer to something that he's probably never heard of before :)

Some notes on Zend Server CE for Mac OS X

22nd June 2009

I've installed Zend Server CE on my Mac to see where it's got to and it's looking quite usable. The installation puts everything into the usr/local/zend directory which is fairly well laid out so that you can find what you are looking for. There's also a a nice admin system at http://localhost:10081 which allows you to restart PHP, view phpinfo(), configure extensions and php.ini. There's also a phpMyAdmin to help administer the bundled MySQL server.

For Mac, this is now one of the better one stop shops for easy PHP & MySQL installation.

Obviously, some things need configuration:

Set up paths

You need access to the command line zendctl.sh and mysql tools:

  • Edit ~/.bash_profile and add:
        PATH=$PATH:/usr/local/zend/bin:/usr/local/zend/mysql/bin
        LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/zend/lib
    
  • Close Terminal and restart it so that your change takes effect.

Change to port 80

The Apache in Zend Server is configured for 10088 to avoid conflicting with Apple's Web Sharing I suppose. The choice of using port 80 would have been nice as an installation option though.

To use port 80 is easy enough:

  • Stop Apache: sudo zendctl.sh stop-apache
  • Edit /usr/local/zend/apache2/conf/httpd.conf and replace Listen 10088 with Listen 80
  • Edit /usr/local/zend/apache2/bin/apachectl and change STATUSURL="http://localhost:10088/server-status" to STATUSURL="http://localhost:80/server-status"
  • If you are using vhosts, then edit /usr/local/zend/apaches/conf/httpd.conf and replace all instances 10088 with 80
  • Restart Apache:sudo zendctl.sh start-apache

Installing PHPUnit

Update PEAR first:

    sudo pear channel-update pear.php.net
    sudo pear upgrade-all

Install PHPUnit:

    sudo pear channel-discover pear.phpunit.de
    sudo pear install phpunit/PHPUnit

Installing Xdebug

  • Install Xcode so you have a compiler!
  • Stop Apache: sudo zendctl.sh stop-apache
  • Go to http://localhost:10081/ and pick the Server Setup tab. Turn off the Zend Debugger and Zend Data Cache and restart PHP
  • sudo pecl install xdebug
  • Edit /usr/local/zend/etc/php.ini and add above the [zend] section near the bottom:
    zend_extension="/usr/local/zend/lib/php_extensions/xdebug.so" 
    
    [xdebug]
    xdebug.remote_enable=1
    xdebug.remote_host="localhost"
    xdebug.remote_port=9000
    xdebug.show_local_vars=On
    xdebug.var_display_max_data=10000
    xdebug.var_display_max_depth=20
    

    (you should set up your xdebug settings as you require!)

  • Restart Apache:sudo zendctl.sh start-apache
  • The Server Setup->Extensions section of the admin interface should now show xdebug.

All in all, it's remarkably easy to set up Zend Server using PEAR and PECL is which how it should be.

The only other gotcha I noticed is that my.cnf is in /usr/local/zend/mysql/data whereas I would have thought that /usr/local/zend/etc would have been more logical.

DPC '09

15th June 2009

The Dutch PHP Conference is over and so it's time to write a short wrap-up.

Day 1

The conference was opened by a cool animated video and then Cal Evans welcomed us, with a nice short speech. The keynote was given by Andrei Zmievski of Digg. Andrei is a core devloper and gave an interesting overview of what we can expect to see next in PHP.

Cal opens DPC 09

I then listened to Paul Reinheimer talk about some problems you can encounter in conceptually easy situations. I found the section about handling account login issues very interesting and it's an area that I now intend to improve in my code. Ben Ramsey followed with a talk on the theory of REST architectures which was interesting, though not directly relevant to anything that we're doing at the moment. Making sure that I understand it when we come to make web service APIs is important though.

After lunch Matthew Weier O'Phinney talked about contributing to open source projects. Matthew gave a great talk with useful information in it. As a contributor to Zend Framework already, I mainly used this talk to learn how to evangelise the concept of contributing to other people.

I stepped out of the next session into the hallway track where I caught up with some people and then checked my email. Then Jan Lehnardt was on to talk about CouchDB. CouchDB fascinates me as it's so different from the relational databases I'm used to. I don't see that we'll be using it soon though - the paradigm shift is significant.

The day ended with the speakers dinner followed by drinking :)

Day 2

Day 2 dawned bright and far too early and I managed to leave my power adapter at the hotel, so I had to go back for it, missing the opening keynote. I got back to see most of Eli White's talk on scaling. Eli is a good speaker and the talk was well researched. I know that if I ever need to scale a website to 20 database servers and too many web servers, then I'm going to try and head hunt him...

I was intending to see Juliette Reinders Folmer's talk on UTF-8, but Paul suffered from a video adapter failure and so I lent him my laptop and stayed to watch and make sure he didn't break it. Paul gave another interesting talk whilst looking good in his suit.

After lunch, it was my turn to talk. Although I was nervous at the beginning, I think that I got into my stride and the presentation went well with intelligent questions asked by the audience. I think it helped that I advised the people who knew more than I did to leave before we started :) If you were there and haven't yet rated it, then please leave feedback!

The final breakout session that I attended was another by Ben Ramsey about HTTP. There was more here that was directly relevant to work, but I'd have preferred more on the codes side with less emphasis on the methods.

The session was closed with a conversation between Cal Evans, Ivo Jansch, Andrei Zmievski, Lorna Mitchell and Paul Reinheimer. This took the form of an interview by Cal and Ivo with their guests. It worked quite well, but I felt that the questions for Andrei and Paul were not as well structured as the ones for Lorna. There was a slide show running above their heads with Twitter and Flickr photos from the conference playing. This was very funny :)

In the evening, I went for a meal at a Pancake house that was very enjoyable and I got to see a little bit of Central Amsterdam!

Conclusion

Overall, The 2009 version of the Dutch PHP Conference was very successful. It's clear that it is being positioned to become a major conference, not just for Europe, but for the world with a significant focus on the advanced developer.

I will certainly be submitting to talk in 2010 - assuming I can think up some advanced topics to talk about!

Cheers!