I'm Chris. A thirty-something husband, graduate, star gazer, aspiring triathlete, explorer, vegetarian, reader, writer, cinemaniac, and lover of life in general.

Born, raised, and currently residing in sunny Bristol, for the past few years I have worked as the Head of Engineering for Zapmap, helping EV drivers better understand where and how they can recharge. Okay, okay, you got me: Bristol isn't even that sunny. I do, though, have over a decade-and-a-half of commercial experience under my belt working with Web technologies, building applications used by millions of people.

Previously I have led the development team at a creative agency, a five-year stint running a development studio producing Web solutions for SME's using our purpose built CMS and eCommerce store, and another 5 years as a Senior Developer for an events listing company (where I made an iPhone app that hit the AppStore front page!). I've created an e-signature SaaS to help companies get their contracts signed, and I've built three (yes, three!) PaaS's for people new to the world of Web development, giving them a simple intro.

Whilst still a fully-fledged developer, I now also undertake more senior level tasks: giving strategy, writing reports and feasibility studies, research and development, specifying projects, recruitment, and mentoring members of the team.

This site exists primarily to permit myself writing about technology, tips & tricks, and my life in general. You can follow what I am currently reading and listening to, and what makes me tick by following me on Twitter, where I try to occasionally spout something witty.

I made Zap-Pay

Date: October, 2020 • Role: Project lead, R&D, Architecture, Multi multi-tenant, Payment processing, OCPI, Laravel, Full test coverage

Screenshots of the GigAlert app on an iPhone

Using Zap-Pay because the EV charger failed to recognise 4 different cards and it's working great. Plus app tells me how much I've charged and cost so far. Nice work Zap-Map!

— Lloyd Watkin, Twitter

As the EV market continues to go from strength to strength, journey planning and paying with one app or membership card must also follow – Zap-Pay will help do just that, propelling us towards cleaner towns and cities and a zero emission future.

— Rachel Maclean,
UK Government Transport Minister

EV drivers can now use a single app to pay for charging across different networks. Say goodbye to lots of different RFID cards and apps. Hooray.

— Green Car Guide

I made GigAlert

Date: October, 2015 • Role: Project lead, R&D, Objective-C, SQLite, Multiple API integrations

Screenshots of the GigAlert app on an iPhone

The app every gig goer has been waiting for. Everything I want from a gig app is here. Excellent up-to-date information and clean and easy to use.

— Noonanio, Apple App Store

Never usually write reviews for apps, but this is an exception. Such a brilliant app for tracking artists. Amazing app, would definitely recomment.

— 375hero, Apple App Store

I was amazed how good [GigAlert] was despite already having another gig app this one still impressed with its ease of use and speed.

— Splatterjay, Apple App Store

One app solution. Great app, has everything you would want for organising your gigs and lets you know when my favourite bands go on tour.

— FoxFray, Apple App Store

Great! Such a good app and means you don't miss a thing. Everything is in one place and it's really easy to use!

— Rebglo, Apple App Store

Splendid app. Very easy to use… even a monkey can do it! My Ents24 account synced all the artists onto my app, no problemo, easy peasy!

— PESwiftly, Apple App Store

I made an Open Source PHP MVC framework

Date: September, 2012 • Role: Personal project, PHP, MVC

Image of the PHP MVC project, and the profiler

A simple, quick and easy to use PHP MVC with Autoloading, Routing, Models, Views, Controllers, Layouts, and Caching. There are plenty of excellent MVC's out there. So why the need for yet another? Simply because they are big and complex. Why use a sledgehammer to crack a nut?

The projects aims to provide a compact codebase providing the basics for any application. It's designed to be fast, really fast, with its built in profiler you can easily see how fast each fragment of your site is. It has been forked many times, and forms the underlying of the Polyfony framework.

I made Ents24's Messenger Bot

Date: April, 2016 • Role: Project lead, AI NLP, PHP, ElasticSearch, Multiple API's

The Ents24 Messenger Bot, using Facebook

An advanced bot that you can talk to via Facebook Messenger and Amazon Alexa. The bot was designed to be used on many different platforms — so its NLP, input, and output are extensible and interchangeable via dependency injection.

Built as an internal R&D project over a two week period which was then presented and demoed to the company at our monthly meeting.

I made an advanced template engine

Date: July, 2008 • Role: Project lead, PHP, Advanced regular expressions

Hello, I'm Chris Hill from Test site name.

{foo} exists and it's value is: bar. In uppercase that is BAR.

Chris Hill's {bar} is: foobar.

Site name is Test site name.

The answer to (16 * 100) + 1 is: 1,601.

User ID User name Users {bar}
1 (You) Chris Hill foobar
2 John Doe I have no bar
3 Joe Bloggs I have no bar
4 Mary Small I have no bar

Developed as part of an online community I built whilst on my final year of university (in-between dissertations and lectures!), and later sold, this parser formed the foundation of the system. It was designed to be as user friendly as possible; you didn't have to be a Web wizard to create a fully functional site. Complete with a user registration/login, forum, messaging, voting, and an admin control panel, it was an early version of sites such as Wix.com and BaseKit.

  • Powering over 30,000 sites
  • Over 200,000 members
  • 2,500,000 page views per month
  • 6,000,000 forum posts

I made an MMOG

Date: April, 2007 • Role: Personal project, PHP

  Defending Attacking
Attacking ship 1
Attacking ship 2
Attacking ship 3
Attacking ship 4
EMP freezing ship
Stealing ship
Salvage ship
Asteroid stealing ship
  • Wave 1
  • Wave 2
  • Wave 3
Defending Attacking
Ship Total Destroyed Frozen Stolen Total Destroyed Frozen Stolen
EMP freezing ship 5,000 1,959 0 0 4,000 3,831 0 0
Attacking ship 1 700 274 0 0 500 479 0 0
Attacking ship 2 2,000 800 0 1,200 3,000 558 0 2,442
Attacking ship 3 1,500 600 0 900 1,750 325 0 1,425
Attacking ship 4 800 313 0 0 400 383 0 0
Stealing ship 1,000 110 320 0 4,000 148 700 0
Salvage ship 500 55 160 0 0 0 0 0
Asteroid stealing ship 0 0 0 0 2,000 1,915 0 0
Totals 11,500 4,111 480 2,100 15,650 7,639 700 3,867
  Defenders salvaged 113,285 primary and 29,215 secondary. Attackers have stolen 10 asteroids.
Defending Attacking
Ship Total Destroyed Frozen Stolen Total Destroyed Frozen Stolen
EMP freezing ship 3,041 10 0 0 169 169 0 0
Attacking ship 1 426 1 0 0 21 21 0 0
Attacking ship 2 2,442 334 0 2,108 1,200 651 0 549
Attacking ship 3 1,425 195 0 1,230 900 488 0 412
Attacking ship 4 487 1 0 0 17 17 0 0
Stealing ship 890 46 13 0 3,852 218 425 0
Salvage ship 445 23 6 0 0 0 0 0
Asteroid stealing ship 0 0 0 0 85 85 0 0
Totals 9,156 610 19 3,338 6,244 1,649 425 961
  Defenders salvaged 166,673 primary and 41,327 secondary. Attackers have stolen 0 asteroids.
Defending Attacking
Ship Total Destroyed Frozen Stolen Total Destroyed Frozen Stolen
EMP freezing ship 3,031 0 0 0 0 0 0 0
Attacking ship 1 425 0 0 0 0 0 0 0
Attacking ship 2 549 549 0 0 2,108 153 0 1,955
Attacking ship 3 412 412 0 0 1,230 89 0 1,141
Attacking ship 4 486 0 0 0 0 0 0 0
Stealing ship 844 130 0 0 3,634 0 424 0
Salvage ship 422 65 0 0 0 0 0 0
Asteroid stealing ship 0 0 0 0 0 0 0 0
Totals 6,169 1,156 0 0 6,972 242 424 3,096
  Defenders salvaged 143,470 primary and 35,030 secondary. Attackers have stolen 0 asteroids.

Built initially as a personal project, it quickly grew into a modestly sized MMOG, requiring a volunteering team of 8 to help run. The general idea is for the attacker(s) to steal as many of the defenders asteroids as possible. The attacker needs to plan wisely, though, as ships only target other specific ships, and there can be multiple attackers and defenders simultaneously.

As the sole developer, I wrote and maintained over 100,000 lines of code, both on the front & backend, as well as the admin control panel, and the database schema. Particular attention needed to be paid to security and speed, as often there would be hundreds of players online at once. The source code for this is hosted on GitHub.

Open Source GitHub projects

There are plenty of excellent MVC's out there. So why the need for yet another? Simply because they are big and complex. Why use a sledgehammer to crack a nut?

A tiny application that will monitor your Memcached server, providing real-time monitoring and up-to-the-second data in a glance-able format.

You and your fellow planetary companions will work as a team within a turbulent galaxy where planets attack other planets for galaxy supremecy.

PHP/JS Reversi
A PHP/Javascript implementation of the Reversi board game.

I have opinions


Personal project: Loan Calculator

Loans can be complicated. This tool aims to give you the knowledge to quickly, and visually, see how changing a little can change a lot. What does a loan look like at 5.0% interest vs 5.25%? What if you borrowed £5,000 less, or added another £100 to the monthly repayment?


The Advocate

I am an INFJ, apparently making me the rarest type in Myers–Briggs Type Indicator: only around 1% of the population. INFJ: Introversion, Intuition, Feeling, and Judging. I walk alongside other INFJ’s such as Martin Luther King, Nelson Mandela, and Mother Teresa.


Broken Windows

There is an interesting theory that came around in 1982 by two American social scientists named James Wilson and George Kelling called “Broken Windows”. This stated that maintaining law and order quickly in urban areas would result in fewer crimes and de-escalating crimes of severity.


Service Manuals

Service Manuals, Playbooks, Style Guides, call them what you want but to any large-ish organisation they are a vital way to maintain consistency among the different departments and outside organisations, to ensure your brand does not get misused and misrepresented.


Cleaning up after yourself

Everyone likes a nice clean interface; some of the required scaffolding simply gets in the way of what we want to do. A classic example of this is closing things automatically; there are several ways to do this (using tweaked code examples from the PHP manual):


Magic Mirror

This guy could be on to something. There is a definite huge gap in the market for a quick and easy way to see what’s going on whilst you get ready, without having to look at your phone and then get distracted on Facebook, Clash of Clans, or an email.


Getting Sassy

My stance on CSS preprocessors in the past has been far from glowing, but I’m slowly coming around. Slowly being the keyword. But I’m there now, I love it. I used to think it was just because of variables, but actually the syntax is nicer than CSS. There, I said it, humble pie. And it’s not just because it’s leaner, it’s actually more maintainable, and I’m going to give you three quick examples why.


Yoda notation

Everyone’s done it, they’ve missed the second equals sign in an if-statement and created an assignment instead. Much tutting, shaking of the head, and a little chuckle ensues as you realise your error. There is a thought amongst some that Yoda notation is the way to go, so named because it switches the comparative’s to produce errors instead of unexpected behaviour.


An introduction to PDO: The basics and benefits

MySQL is/was deeply integrated within PHP. No doubt you have seen and used the mysql_*() functions at some stage, but there is an alternative that makes your database interactions much more reliable. It’s called PDO (PHP Data Object) and here’s a quick guide that should get you up to speed in no time at all.


Update: Reversi board game in PHP and Javascript

I like playing the occasional game of Reversi, and thought it would prove to be an interesting project (creating something like RedHotPawn for chess). Several hours programming later I had a simple working prototype. A couple more hours later I added in some missing features and smartened everything up.


Simple PHP Encryption and Decryption

The need for encryption and decryption in general day-to-day Web programming is quite rare. But it can crop up from every now and again. I use a class that handles both encryption and decryption using mcrypt and the Rijndael algorithm (AES) and a 256 bit key size.


Design Pattern II: Factory

As you might have grasped from the name of the pattern its role is to produce and dispatch a product. In this case a classes. We use the Factory pattern as it is a standard way to create a class which is very similar to other classes by containing the same functions, but implemented in a different way. I always like to use non-technical terms when explaining, and this example will be no different.


Cookie replay attack protection

So let’s jump straight in, what is a replay attack? Essentially a security breach whereby someone poses as someone else using some unique piece of data the user supplied/was issued to/from the Web server. It’s kind of similar to a man-in-the-middle attack. We’re going to be looking at the attack using specifically cookie authorisation, a very common means of implementing a “remember me” function.


Defensive programming

Earlier in the week, whilst implementing a domain registration API into another client project (and pulling my hair out), I thought back to a seminar from university. The module was Component Based Design and it was all about writing code in a standard way, helping to aid both the supplier (API creator) and the client (the person using the API). Although I didn’t realise it until now it actually played a large role…


MySQL is 24 seconds too slow

1246402800. A perfectly valid UNIX timestamp, but one that created some confusion and head scratching in our office for one of our latest internal projects. The problem came around when converting the timestamp into a MySQL date using the FROM_UNIXTIME function which produced the wrong output. The timestamp is perfectly valid, it’s the timestamp for 1st June 2009, 00:00:00 (check it, if you don’t believe me).


PHP __auoload

PHP5 reared it’s head mid 2004, 5 long years ago and all PHP developers rejoiced. Especially me. It gave us lots of new shiny tools to play with, including the obvious improved OO support and my particular favourite: the __autoload function. For all you Java developers out there you know that you never have to include or require files, the Java language instinctively knows where to find them thanks to the…


Battle of the CSS positions

It all began a couple days ago, one slightly dull Tuesday afternoon. The air was thick and the light was dimmed. Ahem, I have a challenge for you; try and place a div underneath another. “Piece of cake,” you say. “That’s hardly a challenge”. Well, not so it would seem. I was perplexed by what I saw for a few minutes, at least. So much that I wrote this article and created a little demonstration.


Submit buttons not submitting

Wow, I have been busy lately, what with a hectic workplace and personal life. But I am here to tell you about a little problem I have known about for years but recently popped up when a friend couldn’t work out what was happening.


POST requests are actually GETs

I found out a pretty interesting, and slightly strange, feature of the HTTP protocol today. When submitting a form as a POST request, if you set the action to the targeted files folder name without the trailing slash it submits the form as a GET request—this caused me to scratch my head over a script for a couple minutes.


Design Pattern I: Singleton

In this first episode of PHP design patterns, we will be looking at the Singleton. The Singleton is available in most, if not all, OO languages. The purpose of the Singleton is to only ever have 1 instance of a class available which supplies the rest of the application with consistent data. I would like to point out that my version of a Singleton may differ slightly from other peoples; design patterns are not exact nor are they set in stone.


Magically dynamic PHP

There are several functions in the PHP language which were made to make classes more accessible and dynamic. I am going to be talking about two of these so called “magic functions” which allow you to set and get information dynamically, whilst also providing a simple log to show you what is really going on behind the scenes. These two functions are of course __set() and __get().


PHP exception handling

Arguably one of the best things to come out of PHP5 was its improved OO support. With OO comes easier separation of presentation, data, and business logic layers which leads to reusable code and better code management, amongst a host of others.