Archive for the ‘PHP’ Category

Zend PHP 5 Certified Engineer

Tuesday, July 15th, 2008

After putting the exam off continuously for about 18 months, I actually got around to taking my Zend PHP 5 Certification exam. I originally scheduled the exam, put it off for a few months, then actually forgot about the exam altogether, only to reminded by google calendar an hour before I was due to take it. The test centre was at least an hour away, so that was a waste of $125. I scheduled the exam again, kept putting it off until I caved in last month and got it done.

The exam itself was considerably harder than the original, I wasn’t all that confident when I clicked the ‘End Exam’ button, but I got the job done. I’m glad I found it harder, I’ve obviously improved my knowledge of PHP since I took the original exam nearly 3 years, so they must have made the certification more difficult to achieve.

As far preparation goes, I read the study guide right through once, making notes along the way. I turned up at the test centre about 20 minutes early and went through my notes. The study guide clearly did a good job!


Zend Certified Engineer

Processing output with SimpleXML

Tuesday, July 8th, 2008

PHP’s output buffering allows you to register callbacks, that will process the output before returning it back up the stack. This feature is usually used in conjunction with handlers added by PHP or it’s extensions such as ob_gzhandler, which gzips the output, or ob_tidyhandler, which passes the output through tidy. As output buffers can be stacked, you can use many handlers in turn using the ob_start function.

<?php 

ob_start('ob_gzhandler');
ob_start('ob_tidyhandler');

?>

Because you can pass ob_start any function name you desire, adding custom handlers is easy. At my current workplace, we needed a quick fix for something we’d overlooked and because we’d (fairly) strictly stuck to generate decent markup, we used an output handler in combination with SimpleXml to manipulate the DOM in our HTML pages. I can’t divulge the what we needed to do or the details of how we did it, but here’s a basic example that will attempt to insert a CSS link to a page.

<?php
function process_output($buffer)
{
    try {
        $xml = new SimpleXmlElement($buffer);
        if (isset($xml->head)) {
            $link = $xml->head->addChild('link');
            $link->addAttribute('rel', 'stylesheet');
            $link->addAttribute('href', 'http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css');
            $link->addAttribute('type', 'text/css');
        }
        return $xml->asXML();
    } catch(Exception $e) {
        error_log($e->getMessage());
        return false;
    }
}

ob_start('process_output');

?>

This code can be added to a file that’s included in every page for a quick fix, but beware of performance hits. A quick test showed adding the above processing dropped this example files performance from 960 requests per second to 795 requests per second.





Fat Models and the Data Access Layer

Tuesday, June 17th, 2008

There’s been some discussion recently on why active record:

  1. Sucks
  2. Sucks - but not like that;
  3. Doesn’t suck

I like the active record pattern, so I don’t think it sucks, but I do think it’s used a little out of context sometimes.

If you’re building a small lightweight app, then I think using your Data access layer as the M in MVC is a logical thing to do. It’s quick, it’s easy and you can extend either your active record in Rails, or extend your Table DataGateway in the Zend Framework and you wont go far wrong.

As soon as your app gets a little more complex, you might want to start creating custom
models that contain more business logic than simply pulling and pushing to the database. If your application is complex enough, chances are your model will need to interact with more than one database table, if not database, so at this point, like Bill Karwin pointed out, your model should be using the DAL, not being the DAL. Loosening the coupling between model and DAL, should also help with automated testing the business logic, in that mock objects could replace the DAL.

The only problem is, I don’t know the best way to do it.

I’m currently learning the ways of the Zend Framework and would be interested to see how people think the best way to implement this kind of complex model. I’m currently leaning toward something like this. I’ve included a Zend_Form object, to show how the Persons model encapsulates more logic than just pushing to and from the database. I think the biggest benefit of Zend_Form is validating input, which I consider domain logic, so should be part of the model. But I’m not sure the best way to make things easily testable, without pushing into the realms of fancy Dependency Injection and what not, which I’m not all that familiar with.

File: application/models/Persons.php

<?php

class Persons
{
    public function findByEmail($email)
    {
        $table  = self::getTable();
        $select = $table->select()
                        ->where('email = ?', $email);
        return $table->fetchAll($select);
    }

    public static function getTable()
    {
        // add some dependency injection?
        return new Persons_Table();
    }   

    public static function getForm()
    {
        // add some dependency injection?
        return new Persons_Form();
    }

    // ...
}

File: application/models/Persons/Table.php

<?php

class Persons_Table extends Zend_Db_Table
{
    protected $_name = 'persons';

    // ...
}

File: application/models/Persons/Form.php

<?php

class Persons_Form extends Zend_Form
{
    // ...
}

At first it may seem that the Persons model just ends up acting as a proxy to the Persons_Form and Persons_Table, but once you start writing methods that use both together, you’ll start seeing fatter models and thin controllers, which is all good.

This really is a request for comments really, as I’m personally not sure about the best way to go about this. Would be interesting if any of the people using the MVC part of the Zend Framework in the real world go about this?

Software development podcasts

Tuesday, June 3rd, 2008

I recently picked myself up an 8GB Ipod Nano, I spend a fair bit of time walking my little dog Murphy and I’ve found it great for both music and more recently podcasts. So much so, that I quickly got few to the few podcasts I was subscribed to, so went in search of more. I’ve listened to and liked very much:

  • PHP Podcasts rss
  • Stack Overflow rss

The new editions to my list are:

  • Audible Ajax rss
  • Code Sermon rss
  • Google Developer Podcast rss
  • WebDevRadio rss
  • The Web 2.0 Show rss

I’ll pipe back in a couple of weeks and give my thoughts on the new ones.

Switching server environments

Monday, May 26th, 2008

After reading John Rockefeller’s post on Handling multiple domains and less recently Richard Heye’s post on displaying errors, I thought I’d write a little post about my qualms with their methods.

I won’t go into too much detail, but both examples use a variable that can be manipulated by the user, $_SERVER['HTTP_HOST']. Richard actually changed his example to use $_SERVER['SERVER_NAME'], but as Chris Shiflett shows, neither are guaranteed to be genuine.

My example relies on having access to the server configuration, but is fairly simple. I think Ruby on Rails uses a similar method.

First we set up our virtual hosts, all pointing to the same codebase, but each getting an individual environment variable set using mod_env.

<VirtualHost *:80>
    ServerName davedevelopment.co.uk
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV davedevelopment.co.uk
</VirtualHost>

<VirtualHost *:80>
    ServerName test.davedevelopment.co.uk
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV test.davedevelopment.co.uk
</VirtualHost>

<VirtualHost *:80>
    ServerName anotherSite.com
    DocumentRoot /var/www/codebase
    SetEnv WEB_ENV another_site
</VirtualHost>

The code then switches on this variable, which should be guaranteed to be controlled by yourself?

<?php
switch($_SERVER['WEB_ENV']) {
    case ‘davedevelopment.co.uk’:
        $message = ‘Welcome to DaveDevelopment’;
        break;
    case ‘another_site’:
        $message = ‘Welcome to another site’;
        break;
    case ‘test.davedevelopment.co.uk’:
    default:
        $message = ‘Welcome to DaveDevelopment Test’;
        break;
}

echo $message;

?>


Being a Lead Developer - Part 1 - Being a mentor

Saturday, May 17th, 2008

I got promoted to my current position, Lead Developer, about eight months ago and I’ve recently been reflecting on what I think I’ve achieved and what I need to improve on, you can consider these posts thinking out loud. The role was newly created when I was appointed, we previously only had developer roles reporting straight to managers.

First, a little background on what we are and do. We are a small IT Department, working as a support team for a multi-disciplinary engineering contractor, including development of bespoke systems, mainly web applications. We’re currently trying to move all these sub-applications into one big application. We currently employ three developers and two trainee developers. The developers work full time on the main application, while the trainees work through training material and small projects to gain experience.

Trainee Developers

When I first got promoted to the position, the main change to my daily work was being mentor to the trainees. When I started as Lead Developer, we didn’t actually have any trainees, but were about to recruit. I was involved in the recruitment process, which was a good experience for me. I had actually asked my manager if I could sit in on a couple of interviews for experience before I got promoted, so I was interested in the aspects of hiring anyway. I did a little background reading on interview techniques [Recommended: 1, 2, 3, 4, 5], particularly regarding programmers and stuck to the technical side of things, allowing my managers to use their experience to judge the ‘people skills’. Things went pretty well, but I’m concerned I probably wont ever do it enough to get good at it. Having said that, I’d rather keep the staff we’ve got than get really good at recruiting.

I inherited a training programme and modified it only slightly, except for the module on working as a team, which I rewrote. The trainees work through the programme completing exercises and taking on mini projects along the way. It seems to work pretty well, but I haven’t given the actual programme any attention recently and should get it updated, to try and introduce some more modern development techniques.

The biggest problem I have, is not doing things for the trainees. Whenever they have a problem and ask for help, the temptation is to big up the keyboard and crank out the code they need. This would have benefits, the trainee gets decent code doing what they need and I can get on with my other responsibilities. The downside is, unless the trainee goes back and studies my code, they’ll never learn. Instead I need to take my time and coax the answers from the trainee and let them solve their own problems, albeit with a little provoking

Recently I experimented with our newest trainee, who came to us with little actual programming experience. For his first project, I gave him the choice of implementing it the slightly harder way, which would take him longer but hopefully he would learn more, or the quick and easy way, leaving the harder stuff until later on. Thankfully he chose the hard way and I set him off on his way to use the Zend Framework. I like the idea of this, I know a lot people find it difficult moving from procedural techniques to object oriented methods, so why bother learning the procedural techniques first? I gave him a pointer by showing him Akra’s superb tutorial and he went from there. On demoing the project to my manager, the trainee was asked “if the system was object oriented?” He replied “No”. He didn’t actually know he’d implemented the whole system, barring the view scripts and the boot loaders in object oriented PHP. At first I thought this was bad, thinking he hadn’t realised what he was doing the whole time, but maybe it’s just that he thought that was just the way things were done. I think this was a success and would be interested to hear how other companies introduce their trainees to frameworks and object oriented principles.

Part 2 - Software tools and methods

Log memory usage using declare and ticks in PHP

Monday, May 12th, 2008

Update:See the first comment, looks a far better and more accurate way of tracking memory usage, thanks Mathieu.

As far as I know, there isn’t any memory footprint profiling in Xdebug, I think there was at some point but they removed it because it was a little flaky. I like to monitor the memory usage within my scripts, and I’ve found this simple snippet can help. I don’t think it’s entirely accurate, but it can help a little. Unfortunately, I don’t think it works all that well on Windows, if at all. All good on Linux though.

<?php

function log_memory() {
    $_SESSION['memory'][] = array(
        ‘time’   => microtime(true),
        ‘memory’ => memory_get_usage(),
    ); // or insert your logging code here
}

declare(ticks = 50); // log every 50 ticks (low level instructions)
register_tick_function(’log_memory’);
$var = ‘a’;

for($i=0;$i<100;$i++) {
    $var .= ‘a’;
}

var_dump($_SESSION['memory']);

?>

PHP Versions in popular Linux Distributions

Thursday, May 8th, 2008

I had a problem today at work, I’ve been coding exclusively in PHP5.2 since it was available and most of the servers I’ve been working for are Debian or Ubuntu based, so I didn’t have any problems until this afternoon. We’ve recently bought a SAN solution from Dell and to gain support we bought two new servers, both with SUSE Enterprise Linux installed, which only comes with PHP 5.1.2. That particular version came out in January 2006. Since then I’ve been using the new DateTime object, the filter functions, memory_get_peak_usage() and sys_get_temp_dir(). And they’re only the problems I noticed. We could install from source, but then we lose the subtle benefits of package management.

So, this lead to me wondering what LAMP versions the popular distros are using, with the help of DistroWatch, I compiled this table. It only shows the community/open source distributions, the commercials counterparts for each are usually at least a year behind, guaranteeing support but only for out of date versions.

Distribution Version Apache MySQL PHP
Ubuntu 8.04 LTS Hardy Heron 2.2.8 5.0.51a 5.2.4
openSUSE 10.3 2.2.4 5.0.45 5.2.4
Fedora 8 Werewolf 2.2.6 5.0.45 5.2.4
Debian GNU/Linux 4.0 Etch 2.2.3 5.0.32 5.2.0
Mandriva Linux 2008.1 2.2.8 5.0.51a 5.2.5
Knoppix 5.3.1 2.2.8 5.0.51a 5.2.3
Slackware Linux 12.0 2.2.4 5.0.37 5.2.3
Gentoo Linux 2007.0 2.0.58 5.0.38 5.2.2
FreeBSD 7.0 RELEASE 2.2.6 5.0.45 5.2.5

Framework Popularity/Favouritism/Biase …

Monday, April 28th, 2008

Started writing this post over a week ago, kind of lost interest, but I polished it off…

After reading a couple of posts this week arguing the corner of both Ruby on Rails and Symfony, I found myself thinking about which framework I like the most. I came to the conclusion that I don’t really have a favourite, just the one I’m currently using. I’ve used the two previously mentioned frameworks, CakePHP a long time ago and more recently the Zend Framework. I like them all. They all do similar things, sometimes in different ways, but having spent a lot of time maintaining and developing ‘frameworkless’ sites, I think they’re all mega. Admittedly, my PHP is far stronger than my Ruby, so I steer towards the PHP ones, but that has nothing to do with the frameworks themselves.

Anyway, this lead me to have a little look on Google Trends, to see how many people are searching for what on the framework front, I included the previously mentioned four and Django, which is very popular, but my Python is worse than my Ruby, so I’ve not used it. I know this is hardly conclusive, but it was worth a look.

The results are pretty much what I expected. Django looks like it’s a more common search term, but is starting to rise recently. Zend, CakePHP and Symfony are all slowly on the up, whereas Rails clearly had a big boom over the previous two years and is now settling down a bit.

Google Trends for Frameworks

How To: Simple database migrations with Phing and DbDeploy

Monday, April 14th, 2008

Introduction

This How To will introduce some simple database migrations to your PHP application. Ruby on Rails is a popular web application framework, that provides a method of migrating (upgrading) the applications database programatically, keeping the database schema essentially version controlled. This allows individual developers to update their working databases and the databases on testing, staging or production machines to be updated with new versions of applications. The CakePHP framework has recently developed a migrations library simliar to rails, but this article focuses on using seperate tools to run database migrations, a build tool called Phing, along with a method for creating database migrations, dbdeploy.

Install Phing

I always use the beta or release candidate of phing and for the purposes of this article I suggest you do too. The best way to download and install phing is using PEAR. This can be done on Linux or Windows assuming you have the pear script in your PATH with three shell commands.

shell> pear channel-discover pear.phing.info
shell> pear config-set preferred_state beta
shell> pear install phing/phing

Example Application structure

As an example, we’re going to develop a simple application with the following directory structure.

example/
 |-- db/
 |   `-- deltas/
 |-- deploy/
 |   `-- scripts/
 |-- library/
 `-- public/

The db directory contains sql files for using and manipulating our database and
the deploy directory contains our build scripts that set the migrations in motion. The library directory contains our application code and the public folder will contain scripts and files accessible directly from the web, but will not be the focus of this article.

Build scripts

This section shows you how to develop the build scripts that will run the database migrations. The first file we need to create is a simple configuration file and should be fairly self explanatory. The file is written as key=value, lines beginning with a # are comments. Open your editor and save the following text as deploy/build.properties.

# Property files contain key/value pairs
#key=value

# This dir must contain the local application
build.dir=../

# Credentials for the database migrations
db.host=localhost
db.user=user
db.pass=password
db.name=example

# paths to programs
progs.mysql=/usr/bin/mysql

The next file we are going to create is the deploy/build.xml file. This is the file that tells Phing what we want it to do. I’m not going to go into too much detail describing each part of the build file, there are some comments, but you should consult the Phing Documentation for further details and enhancements.

<?xml version="1.0" ?>
<project name="PurpleMonkey" basedir="." default="build">

    <!-- Sets the DSTAMP, TSTAMP and TODAY properties -->
    <tstamp/>

    <!-- Load our configuration -->
    <property file="./build.properties" />

    <!-- create our migration task -->
    <target name="migrate" description="Database Migrations">  

        <!-- load the dbdeploy task -->
        <taskdef name="dbdeploy" classname="phing.tasks.ext.dbdeploy.DbDeployTask"/>

        <!-- these two filenames will contain the generated SQL to do the deploy and roll it back-->
        <property name="build.dbdeploy.deployfile" value="deploy/scripts/deploy-${DSTAMP}${TSTAMP}.sql" />
        <property name="build.dbdeploy.undofile" value="deploy/scripts/undo-${DSTAMP}${TSTAMP}.sql" />

        <!-- generate the deployment scripts -->
        <dbdeploy
            url="mysql:host=${db.host};dbname=${db.name}"
            userid="${db.user}"
            password="${db.pass}"
            dir="${build.dir}/db/deltas"
            outputfile="${build.dir}/${build.dbdeploy.deployfile}"
            undooutputfile="${build.dir}/${build.dbdeploy.undofile}" />

        <!-- execute the SQL - Use mysql command line to avoid trouble with large files or many statements and PDO -->
        <exec
            command="${progs.mysql} -h${db.host} -u${db.user} -p${db.pass} ${db.name} &lt; ${build.dbdeploy.deployfile}"
            dir="${build.dir}"
            checkreturn="true" />
    </target>
</project>

That’s essentially all the magic we need. Now we just need to create our database.

Writing dbdeploy delta scripts

We haven’t actually created our database, so rather than create it the traditional way, we will actually use the migrations to create the initial schema. We’ve not actually decided what our example application does yet, but seeing as most tutorials make blogs, why don’t we give that a bash. We’ll start simple, one table with three columns called post.

Field Type Comment
title VARCHAR(255) The title of our post
time_created DATETIME The time we created our post
content MEDIUMTEXT The content of our post

Dbdeploy works by creating numbered delta files. Each delta files contains simple SQL to both deploy the change and roll it back. The basic layout of a delta file is like so.

--//

-- Run SQL to do the changes

--//@UNDO

-- RUN SQL to undo the changes

--//

We are creating our initial schema, so put the following content in db/deltas/1-create_initial_schema.sql

--//

CREATE TABLE `post` (
    `title` VARCHAR(255),
    `time_created` DATETIME,
    `content` MEDIUMTEXT,
);

--//@UNDO

DROP TABLE `post`;

--//

Migrating the database

We are one step away from running our first migration. To keep track of the current version of the database, dbdeploy requires a table in the database. This is the only time we will have to interact with the mysql client directly.

shell> mysql -hlocalhost -uroot -ppassword example
mysql> CREATE TABLE changelog (
  change_number BIGINT NOT NULL,
  delta_set VARCHAR(10) NOT NULL,
  start_dt TIMESTAMP NOT NULL,
  complete_dt TIMESTAMP NULL,
  applied_by VARCHAR(100) NOT NULL,
  description VARCHAR(500) NOT NULL
);
mysql> ALTER TABLE changelog ADD CONSTRAINT Pkchangelog PRIMARY KEY (change_number, delta_set);

We are now ready to run our first migration and create the initial schema for our application.

shell>cd deploy
shell>phing migrate

All being well, we now have a posts table in our database. But what about an author for our blog posts? We’ll have to add another table and a foreign key from the post table to author table. To do this we create another delta, we call this one db/deltas/2-create_author_and_link_to_post.sql

--//

CREATE TABLE `author` (
    `author_id` INT(10) unsigned auto_increment,
    `name` VARCHAR(255),
    PRIMARY KEY (`author_id`)
);

ALTER TABLE `post` ADD `author_id` INT(10) unsigned NULL;

--//@UNDO

ALTER TABLE `post` DROP `author_id`;

DROP TABLE `author`;

--//

Run our migrations again.

shell> cd deploy
shell> phing migrate

Conclusion

That’s pretty much it, you’ve seen how to create database deltas and use them to migrate your database, if you can’t be bothered to copy and paste things to try for yourself, download the example application.

There are plenty of caveats when it comes to version controlling databases, especially if you branch and merge your application code, some are detailed in the dbdeploy documentation

This tutorial is probably incomplete or wrong in plenty of ways, if you think you have something to point out, please leave your comments below