Image Masking with CSS and HTML

A recent web design called for the following:

  • the client must be able to upload their own banner images
  • the banner image was not square and had a transparfent mask around over it (in Photoshop, the banner image was underneath a clipping mask)
  • The design must function in a range of legacy browsers

This presented a major headache. Usually uplaoding a totally square image is easy – a client can do this with ease themselves. However, the client in question has no experience using using Photoshop (and why should they to update their website?) and wouldn’t be able to upload a masked image. Additionally, using some of the new CSS3 image masking properties are out, as I need to support IE6 and above.

So, the solution here is to use a transparent image to overlay the square image – meaning a client can upload a square image and have it show masked on the live website – see the final result of what we’ll be making.

Continue reading Image Masking with CSS and HTML

Best Practices With PEAR Cache Lite

Caching a website using PEAR Cache Lite has many benefits – it will speed up your site and is very simple to implement. However, there are several common pitfalls they could cause potential issues on a website. Basically, you can’t approach caching from a single angle, as the type of caching used is always project/problem specific.

Full File Level Caching

Full file caching is the simplist method and essentially takes an image of the page at a particular time. This method is very fast to implement but does have it’s downsides. As you are storing a static file of the page you’ll instantly notice the following issues (I’ve included some typical examples you’ll run into):

  • Any elements of your page that require session data will fail to work (you’ve essentially cached the session id too!)
  • If the page needs to be served using a particular header you’ll be out of luck, as a statiuc file will always be served using a plain text header (E.g. a cached rss feed won’t validate as the header has changed)
  • Clearing the cache becomes very clumsey as the whole cache requires cleaning when even a small change is made (E.g. say a new article is added by the admin)
  • User logins that make use of session data
  • E-Commerce sites and a shopping basket summary
  • Search results pages

With full file caching dynamic content will always be a issue. However, full file caching CAN help high traffic sites, even when a short cache lifetime is set – use with caution!
Continue reading Best Practices With PEAR Cache Lite

PHP Image Uploads – Better File Type Checking

When working on a project I came across a neat snippet of code that will uses PHP’s image manipulation functions to check the uploaded image type. The majority of the time the filetype is checked using PHP’s string functions on the file name, as a string E.g.

$myFile = $_FILES['myFile']['name'];
$allowed_filetypes = array('.gif', '.JPEG');
$ext = substr($myFile, strpos($myFile,'.'), strlen($myFile)-1);

This is fine, but the contents of $myFile can be faked. A much better check for allowing only image file uploads would be to do the following – I thought this was quite neat:

if (!$img = @imagecreatefromgif($path_to_image)) {
  /* NOT a .GIF image */

imagecreatefromgif will return false if the image is not a GIF. A similar thing can be done for checking PNGs (see imagecreatefrompng) and JPEGs (see imagecreatefromjpeg).

Populate Select Boxes using a Global Associative Array with PHP

The following post is being written because today I’ve been annoyed, very annoyed. I’ve been working on updates to a previous developers mini CRM system that I inherited, unfortunately. Basically, the customer wanted to amend the list of options that appear in a HTML select box, on pretty much every page. In this case, 24 pages.

Ok, easy job – or so I thought. If the previous developer hadn’t been a total mong this simple update would have taken a minute or so – simply update a common function, database or global array to repopulate the drop down list options. No luck in the least – the developer had hard coded each drop down into every page, using HTML – **** great! So I just spent close to 40 minutes wading through include files and HTML to make my changes – so unecessary.

So, what follows is a very simple method to have a common drop down list that will be included on any page you want, with the data stored in a global array (could be a database, but a global array is quickest:

The include, model or config file – simple an associative array that will be accessible throughout your application (lets call this file includes.php):

Continue reading Populate Select Boxes using a Global Associative Array with PHP

Passing Arguments as an Associative Array to a Function

Sometimes is it useful and slightly cleaner to pass arguements to a function via an associative array as opposed to a list of variables. There are a variety of methods to achieve this, such as using PHP’s extract function – but the below is cleaner in my opinion. Please note, the following functionality is common place when using a good MVC framework, or a good CodeIgniter base class. Take a sample PHP class:

class setOptions {

    var $temp = '/default_temp/';
    var $upload = '/default_upload/';
    var $cache_time = '0';
    var $cache_status = '0';
    var $cache_file = 'users.txt';

    function __construct($user_settings)
        if (is_array($user_settings)) {
            foreach($user_settings as $k=>$v)  {
                $this->assignSetting($k, $v);
        } else {
            die('Config Error!');

    function assignSetting($name, $value)
        $whitelist = array('temp', 'upload', 'cache_time', 'cache_status', 'cache_file');

        if (in_array($name, $whitelist)) {
            $property = $name;
            $this->$property = $value;


In lines 3 – 6 we set the default values of our settings that are used an our class. We can choose to leave these as they are, or pass the class an array of new setting, to overwrite them.

In line 8 the settings array, as an associative array, is passed to the magic construct function so all the settings are available when the class is called. On line 10, we check to ensure that the data passed to the function is actually an array and on line 11 we simply through each key/value of the array.

On each iteration, the assignSetting function is called (line 17). The function takes a setting name and value as it’s arguements. On line 19 a whitelist of allowed settings is created as an array. Line 20 checks to ensure the setting we are attempting to add is within this whitelist.

Continue reading Passing Arguments as an Associative Array to a Function

The Importance of Client Requirement Analysis

Recently I developed a small bespoke CRM system for a client, based on list of requirements gathered by a colleague approximately 2 months ago. The CRM was nothing out of the oridinary – a maintable customer database, customer login system, email marketing functionality, customer account reminders, invoice associatiion with specific customers etc.

Overall, did the customer get what they? Yes. Did the project take a lot longer than it should have? Definately! The reason for the latter – poor initial requirements analysis from my colleague.

Continue reading The Importance of Client Requirement Analysis

PHP Email Template with Flat Files

It’s quite common when sending an email message to see the following code to set the message body:

$body = "Hi $firstname $lastname,<br /><br />
	Thank you for you recent order - reference <strong>$order_id</strong><br /><br />
	A secure payment for your order of <strong>&pound;$order_value</strong> was successfully processed.<br /><br />
	The estimated delivery date is <strong>$order_date</strong>.<br /><br />
	The Admin";

This is quite messy and mixes html and php, which isn’t ideal – ideally, we’d want a php email template for use across our whole site. Additionally, this code is time consuming to update as you need to manually go back to the raw PHP code if you needed to change the email.

A very simple solution is to use a flat file (.txt file for example, although could be a html or .tpl file) to store the basic email content with placeholders to replace various bits of information that change. For example, part of a template may contain:

Hi {firstname} {lastname},

All the information srrounded by the curley brackets (I’m sure they have a proper name) are the parts of the email that will change. All we need to are pass information to each of these using our very very simple email templating system:

Firstly include the path to your template file. If the file doesn’t exist, stop the script immediately:

Continue reading PHP Email Template with Flat Files

Associate Products with Multiple Categories Using MySQL

Having a database structure that allows a product to be associated with more than one category is a very common scenario in any eCommerce website. However, after working on a couple of truely awful bespoke solutions from other developers recently, whose methods to store and retreive such data were so convoluted, have inspired me to write this article.

Story such data need to not be overly complicated. The following, simple, table structure is required (in a real ecommerce system you would definately have additional fields – these have been omitted here for thae sake of the example):

product_id (PK)

category_id (PK)

product_id (PK)
category_id (PK)

The products_category table is a simple linking table that allows a many-to-many relationship between the product and category table. It contains to two primary keys to ensure every combination of product and category is unique. for example, this table will contain many unique number pairs and a row may be 1,4 or product_id 1 and category_id 4. The files to create and populate this table structure with sample data can be found here.

Now it is simplay a case of running a series of MySQL statements (I’d advise converting them to stored procedures for more security and better application seperation) to retreieve the appropriate data. For example:

Products Within a Certain Category (E.g. category_id 1):

SELECT p.product_id, FROM product p
INNER JOIN product_category pc
ON p.product_id = pc.product_id
WHERE pc.category_id = '1';

Count Products Within a Certain Category (E.g. category_id 1):

SELECT COUNT(p.product_id) As myCount FROM product p
INNER JOIN product_category pc
ON p.product_id = pc.product_id
WHERE pc.category_id = '1';

…and that’s it. Extremely simple, can be expanded to any eCommerce system and not convoluted at all :)

Multiple Categorisation for SEO

A very common technique in ecommerce, is for products to be assigned a single category – part of the filing cabinet approach to site development. This works for niche ecommerce stores, but not for the majority. For example, a tshirt might belong equally in the following categories:’ red tshirts’, ‘logo tshirts’, ‘mens tshirts’ etc. Additionally there are times when it makes sense to have a multiple categories for a product and can help with conversions(a totally different topic).

The special care of multiple categories and SEO is that category pages contain a huge amount keyword rich anchor text. Yes, the majority of ecommerce software and system will allow filtering of results, but the canonical url tag is often used and results in messy links that are not ignored by search engines.

The major issue here is duplicate content – frowned upon by Google and can cause real issues for your site. Yes, a small numbers of pages is within acceptable limits, but when you have store that has hundreds of products duplicate content really can become an issue.

Using our tshirt example from above, say we place a product called ‘super baggy tshirt’ into the ‘red tshirts’ and ‘logo tshirts’ categories – the following two urls would be produced by our ecommerce software – the below structure is very common):

At first glance, this all looks well: SEO friendly URLs, well structured, organised and keyword rich. All this correct, apart from the fact that both URLs represent the same product – here is our duplicate content issue. The duplicate content issue will get worse if the product is placed into more categories.  The easiest solution is to rewrite our product URL to something much simpler:

This will allow us to place the product into as many categories as we need without creating any duplicate content at all – there will always be a single version of the product URL.