Log memory usage using declare and ticks in PHP

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

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 …

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

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

Contributing to Open Source Software

April 3rd, 2008

I’m a big fan of Open Source Software. Although I’m sure I could get by if I had to move to proprietary based software, at the present time, open source software earns me a living. Because of this, at the start of the year, I decided to give something back and start contributing to open source. I chose the Zend Framework, because it is written in PHP and is a project I have a lot of interest in. I registered for an account on the bug tracker and signed the CLA, but that’s as far as I got. I started looking through some of the bugs available for fixing, but found that the simpler ones were being dealt with quickly by other people and the only ones left where a little too complex for me. I still plan to contribute before the year is over. I intend to use the framework for a project I have in mind and the frameworks current implementation of a client for Amazon Web Services needs adding to for the purposes I need, so maybe I can contribute that way.

Back to the point, today I think I found a bug in PHPUnit, I couldn’t work out how to submit a bug report via the website, so I emailed Sebastian Bergmann with a patch. I’m not going to describe the bug until I know for sure that I’m correct, but I’m at least 90% sure I’m in the right. So, if I am right, that’s my first solid contribution to open source software.

Update

Well it seems I was right in reporting the bug, but it appears Sebastian didn’t like the patch I sent, or more likely it didn’t work. This changeset looks slightly different to the patch I submitted.

Index: PHPUnit/Util/Metrics/Function.php
===================================================================
--- PHPUnit/Util/Metrics/Function.php   (revision 2707)
+++ PHPUnit/Util/Metrics/Function.php   (working copy)
@@ -449,7 +449,7 @@
         }

         else {
-            $this->crap = pow($this->ccn, 2) * (pow(1 - $this->coverage/100, 3) + $this->ccn);
+            $this->crap = pow($this->ccn, 2) * pow(1 - $this->coverage/100, 3) + $this->ccn;
         }
     }

From what I can tell, the change put into place is also incorrect according to the C.R.A.P. index formula.

Update 2

I emailed Sebastian and he fixed it properly in changeset 2712

Linux/PHP one liner - Syntax check all files.

March 25th, 2008

Here’s a simple one liner you can use to syntax check all php files in your working directory.

find . -type f -name "*.php" -exec php -l {} \; | grep -v 'No syntax errors'

For those not familiar with the programs used, it basically reads as…. Find all files that end in ‘.php’ and with each of those files run php -l. This is then put through a pipe to the grep -v, which filters out all files that are syntactically correct.

Sifr turned off

March 20th, 2008

I noticed some problems with my browser (FF2/Ubuntu) with the Sifr headings on the posts, so I’ve commented them out, sorry about the horrible blue heading links ;)

10 tools for Modern PHP Development

March 20th, 2008

A simple list of tools for modern PHP development. There are alternatives to most of the tools, but I’ll list native PHP tools wherever possible.

1. PHPUnit

PHPUnit is a testing framework belonging to the xUnit family of testing frameworks. Use it to write and run automated tests. Start using PHPUnit

2. Selenium RC

Selenium RC can be used in conjunction with PHPUnit to create and run automated tests within a web browser. It allows tests to be run on several modern browsers and is implemented in Java, making it available to different platforms. PHPUnit and Selenium

3. PHP CodeSniffer

PHP CodeSniffer is a PHP code tokenizer, that will analyse your code and report errors and warnings based on a set of Coding Standards. Documentation

4. Phing

Phing is a project build tool and is a PHP port of the popular Java program ant. Phing can be used to automate builds, database migration, deployment and configuration of code. Documentation. Database migrations with phing

5. Xdebug

Xdebug is a multi-purpose tool, providing remote debugging, stack traces, function traces, profiling and code coverage analysis. Debug clients are available in many PHP IDEs and even plugins so you can debug from everybody’s favourite editor vim. Documentation

6. PHPDocumentor

PHPDocumentor is an automated documentation tool, that allows you to write specifically formatted comments in your code, that can be brought together to created API documentation. Tutorial

7. phpUnderControl

phpUnderControl is a patch for the popular Continuous Integration tool, CruiseControl. Together with the previous six tools, phpUnderControl gives you a great overview of the current state of your application/codebase. Keep an eye out for Xinc

8. Zend Framework - or <insert your favourite framework here>

Frameworks facilitate the development of software, by allowing developers to focus on the business requirements of the software, rather than the repetitive and tedious elements of development, such as caching. There are plenty of frameworks to choose from, but I particularly like the Zend Framework. Have a read through this excellent Getting started guide

9. Subversion

Subversion is a revision control system that has superceded CVS. If you’re writing software of any kind, you shoud be using version control software.SVN Book

10. Jira

So I could have named one of many, but this is the one I’ve liked the most recently. Jira is a bug/issue tracking software package and can also help with project management in terms of goals and roadmaps. Most issue trackers link to version control repositories, such as Subversion. Only downside to Jira is that it costs for non open source projects.

I’m pleased to say that with a little bit of pushing and persuasion by myself, we are currently using all of these technologies with the exception of Jira, we have a bespoke issue tracker.

What do you think to the list? Anything I have missed? Any alternatives you prefer?

New site - LimoTrack.co.uk

September 23rd, 2007

Kind of pre-launched a site for a friend this week, he’s started a new business with a slight twist of a limosine service, he’s going to be ferrying people around in a fully-tracked articulated vehicle, which is kind of like a tank people carrier. Will post later with a press release and a few technical tidbits on the site.

Hardman LimoTrack

Capistrano, Migrations and Which-Broadband updates

September 11th, 2007

I’ve been sitting on some code updates for www.which-broadband.net for a while now, what seems like ages ago I added a simple news section and adding link redirecting along with click tracking, but didn’t get around to releasing it. I actually made a couple of sales of the site the last couple of months, so I thought I’d make a little effort to tidy things up, but decided to do it the long winded way and learn something in the process. I’ve read lots about Capistrano before, but never really put it into practice, now seemed like the time and also to try the ActiveRecord’s migrations. Most of it went swimmingly, the biggest annoyance I found was ActiveRecords MySQL implementation, in that the BIGINT’s I had were only integers to ActiveRecord so once I created the database with migrations, the columns wouldn’t hold a number large enough. I got round this by making the columns strings and overiding the accessor and modifier in the model in question and then things were fine. I also had problems where I was reading the Capistrano one manual, but using version 2, which has some major differences. Anyway now I have an updated version of my site online, plus an automated deployment tool readily available, lets hope I’ll make more frequent updates. I’m doing a few little tests with AdWords to see if I can do any click-flipping, if nothing works I’ll just leave it alone for now, don’t have the time to push it too hard.