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.

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.1.x (or 5.5.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 channel-update pear.php.net
  2. sudo pear upgrade-all
  3. sudo pear channel-discover pear.phpunit.de
  4. sudo pear install phpunit/PHPUnit

It all works on this machine, anyway :)

Other options:

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.