IPC 2009

23rd November 2009

The International PHP Conference 2009 took place last week in Karlsrule, Germany.

The audience

This conference has presentations in both English and German, though fortunately, there was always at least one English session in each time slot! I managed to get to a fair few sessions.

Cal Evans' talk on Zend Framework command line applications was an especial highlight as it's an area that we could do better and I now know how to! Similarly, we recently wrote a SOAP Server for a project using Zend_Soap which has been educational. David Zülke's talk on SOAP filled in some gaps in my knowledge which was useful.

Zend Framework URL Rewriting in IIS6

16th November 2009

I've written before about URL rewriting with IIS7's URL Rewrite module.

IIS6, which ships with Windows Server 2003 does not have this module though and guess which version my client's IT dept run? As usual, they wouldn't install ISAPI_Rewrite or one of the other solutions for me. In the past, I've simply written a new router that creates URLs with normal GET variables, but this is ugly and I wanted better.

One thing IIS6 does let you do is configure a URL to be called upon a 404 error, which then allows you to have "pretty" URLs and be able to route them.

Firstly, I set up the URL handler in the IIS Manager:

Screen shot 2009-11-13 at 07.46.59-1.jpg

This will result in all unrecognised URLs being redirected to index.php. The standard Zend_Controller_Request_Http object will automatically extract the URL and routing works as expected.

However, there are three problems:

  1. The $_POST array is always empty
  2. $_SERVER['REQUEST_METHOD'] is always GET, even for a post request
  3. The first key in $_GET has been mangled by IIS

As Zend Framework wraps up the request into a Request object, this is fairly simple to work around by creating our own Request object.


class App_Controller_Request_Iis404 extends Zend_Controller_Request_Http
{
    /**
     * Constructor
     *
     * If a $uri is passed, the object will attempt to populate itself using
     * that information.
     *
     * @param string|Zend_Uri $uri
     * @return void
     * @throws Zend_Controller_Request_Exception when invalid URI passed
     */
    public function __construct($uri null)
    {
        // As Zend_Controller_Request_Http accesses the superglobals directly, we
        // will have to write into $_GET and $_POST directly

        // The post variables can be accessed from php://input
        $input file_get_contents('php://input');
        if (strlen($input)) {
            $input urldecode($input);
            parse_str($input$_POST);
        }
        
        // fix $_GET
        foreach ($_GET as $key=>$value) {
            if (substr($key04) == '404;') {
                // special key created by IIS - the actual key name is after the ?
                $bits explode('?'$key);
                if (count($bits) > 1) {
                    $_GET[$bits[1]] = $value;
                }
            }
        }
        
        return parent::__construct($uri);
    }
    
    /**
     * Return the method by which the request was made
     *
     * @return string
     */
    public function getMethod()
    {
        if (!empty($_POST)) {
            return 'POST';
        }
        
        return parent::getMethod();
    }
}

We start by reading the php://input stream which on a POST request will hold the POST variables. We can then transfer them to the $_POST array. Similarly, the key in the $_GET array that has been mangled, is easy to detect as it starts with '404;'. We can then find the ? and the part after it is the real key, so we create a new $_GET element for that item. Finally, we override getMethod() and return 'POST' if there are any elements in $_POST.

To use a custom Request object, you need to create an _init method in your Bootstrap:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    function _initIis404RequestObject()
    {
        $this->bootstrap('frontController');
        $frontController $this->getResource('frontController');
        $frontController->setRequest($options['frontController']['requestClass']);  
    }

Zend Framework's standard URLs now work nicely with IIS6 on Window Server 2003.

ZendCon 2009

13th November 2009

I know I'm late on this one, and I only have the pathetic excuse of being busy. However, ZendCon 2009 was a great conference and I want to thank Eli, Zend and S&S for putting it on.

Andi wraps up ZendCon 09

I gave two talks; a Zend Framework Certification refresher tutorial and a talk on project management. Overall I was happy with how both talks went. I think that my presentation style has improved considerably over the last year as I am much more confident and it shows. Hopefully most of the people in the sessions gained from them.

As always, I learnt new things in other sessions I attended, learning about Solar, Zend Framework, deployment, MySQL and countless other things. I also gained from meeting the many people who were there. The conversations outside of the sessions are equally as valuable as I learn tips and tricks from people facing the same sort of problems that I do.

We also socialised after hours too:
Ilia and the elephpant!

All in all, a great conference, and I hope that I manage to get there again in 2010.

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.

Introducing yourself at a conference

6th October 2009

I'm going to be at PHPNW 09, ZendCon 09 and IPC 09 this autumn and fully expect to meet people that I know online, but haven't met in person before.

The big problem for me is that I have trouble connecting the dots, so if we end up talking, please mention where I might know you from.

For example: "Hi, I'm John. You might know me as phpsupercooldude on the zftalk channel on freenode"

and I'll be able to place you correctly and may even remember you the next time I see you!

Setting up PHP & MySQL on OS X 10.6 Snow Leopard

5th October 2009

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 version of MySQL 5.0.x for OS X 10.5 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
    

    Quit Terminal to flush the history to file. Restart Terminal and remove the history file: rm .bash_history 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 install xdebug
  2. Edit /etc/php.ini and add
    zend_extension="/usr/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so"

    after the other extension lines.

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

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 :)

Tutorial Q&A PDF

1st September 2009

Chris Kirk has kindly provided a Q&A PDF which summarises a number of problems that have been raised and answered in the comments on the tutorial page. If you are having problems, download it and see if it helps.

Thanks Chris!

Three years of my Zend Framework Tutorial

16th August 2009

Three years ago today, I published my first Getting Started with Zend Framework tutorial. This was the announcement. Back then, Zend Framework was at version 0.1.5 and a considerably smaller download than now :)

Three years later and I haven't lost my enthusiasm for Zend Framework as you can tell since the latest version of the tutorial supports ZF 1.8 and 1.9 and uses the new features like Zend_Application and the command line Zend_Tool scripts. And I wrote a Zend Framework book!

I wonder what will happen in the next three years?!