Category Archives: PHP

How to remove absolute image srcs in WordPress

I use WordPress for this site but to be honest, I absolutely hate WordPress.

Comment spam, Malware hacks, hostname is part of the config, answer to everything is a plugin, etc, etc, yuk, yuk, yuk.

I use it because all I want to do is make posts, and for that, it is fine. A lot of other people use it for Content Management on complex websites, and that’s where it starts to fall apart.

For instance, lets say you have a pretty important website, where you want changes to be verified by the site owner before they go live. So you do the sensible thing, and create a staging environment (staging.mysite.com), and promote code and DB changes to your live site (www.mysite.com) directly from your staging site, rather than manually updating your live site.

That’s the way things are done in the grown up Internet, but if you try to do this with WordPress, you’ve entered a world of pain.

When you use WordPress’s Media Library to put an image in a post, WordPress insists on creating an absolute src attribute for the image, including the protocol and the hostname.

eg

<img src="" src="http://staging.mysite.com/wp-content/upload/catpic.jpg" />

when ideally it should be using an absolute URL without the protocol and hostname

ie

 <img src="" src="/wp-content/upload/catpic.jpg" />

This means that you can’t port your site directing from staging to live, as your live site will contain images that are being pulled from your staging site. The same problem applies if you are changing your site to a completely different domain name.

Consulting the WP forums you will find all manner of solutions to this, ranging from (yes, you’ve guessed it) plugins, to running MySQL queries every time you want to update you site.

A much simpler way to do this is to user JQuery, which you insert into your code once (in script tags in the footer of your theme), and then never worry about again.

The necessary JQuery is as follows:


jQuery('img').each(function () {
       var curSrc = jQuery(this).attr('src');
       if (curSrc.substring(0, curSrc.indexOf('/', 4)) == 'http:') {
          var baseURL = curSrc.substring(0, curSrc.indexOf('/', 14));
          jQuery(this).attr("src",curSrc.replace(baseURL,""));
       }
});

What this does:

Each time your page loads, JQuery will cycle through all the images on that page. If it finds an image src that includes the protocol specifier ‘http:’, it will check what the base URL of your page is, and remove that value from the src of the image.

This will leave you with a page on which all the images are loaded relative to the root of your web server, rather than a Fully Qualified Domain Name.

How to use git to maintain code between 2 computers

I recently decided to switch from using a traditional Intel based laptop to a Macbook (I know Macbooks also use Intel chips now, but you know what I mean).

Rather than simply make a tarball of all my code projects that I would ship across my network to the new system, I decided to try and be a bit more professional and give git a try.

All things being equal, a single developer working on a code project probably doesn’t need source control, but I figured it was probably wise to learn this, in case some situation arose in future where I was required to collaborate, and where it was important I didn’t look like a complete novice.

I have had some experience with git before, but this was pretty pedestrian, and it didn’t touch on the main challenge with git, which is working from multiple sources with remote repositories.

For the uninitiated, git is a source control system, but not like a traditional source control system.

In a traditional system, the history of changes to a particular code project are stored centrally. In the git system, each participant in the project retains a local history, which they can work on locally, or merge back to the central repository. This logic is somewhat convoluted when you are used to working with a centrally stored repository, which means git can take a bit of getting used to. This isn’t really helped by the syntax of the commands used in git, which are anything but self-explanatory.

I won’t go into git any more than this, because its way more complex than can be explained in a single post. Instead, I’ll focus on the task described by the post title; if you want to learn more about git that this provides for, you’ll have to read a bit more elsewhere, and do quite a bit of trial and error.

OK, so the basic components of the task are:

1. An Internet hosted git repository (repo)

2. Computer 1 with the git client installed

3. Computer 2 with the git client installed

There are several options available for creating an Internet hosted git repo, many of which offer a free basic level of service. I choose Bitbucket. I registered, signed in and create a repo. In completing this task, Bitbucket signalled the commands and URL I would need to work with the repo. Thank you Bitbucket for making life with git a little easier. For the purposes of this post, lets say I’m creating a repo to manage the code for this blog, so I’ve called it “nbfblog”

Next to Computer 1. The installation of git is very straightforward, so I won’t cover it here. Just Google it for your particular OS.

Once installed, you now need to create your local repo. Change to the directory in which your code is stored, and issue the following commands:

git init

git add .

git commit -am "initial checkin"

These commands will create your local repo.

The next task is to create what is referred to as a remote of this repo. When we were on Bitbucket, we basically created an empty repo called nbfblog. We are now going to populate that repo by creating a remote of our local repository. The terminology isn’t great here, which is kind of an issue throughout git.

To create your remote, issue the following command:

git remote add origin https://garrethmcdaid@bitbucket.org/garrethmcdaid/nbfblog.git

This creates a remote called origin, in the Bitbucket account that is identified by the username garrethmcdaid, in the repo nbfblog. Depending on how git is set up on Computer 1, you may or may not be asked for your Bitbucket password when you issue this command.

At this point, all you have done is create a remote. No code as been moved between Computer 1 and the central repository. To do this, issue the following command:

git push -u origin --all

If you’re used to using the command line, you’ll probably presume that the -u argument here means user. Again, its no harm to remind yourself that the git command syntax is misleading; it this instance, -u means upstream, and signifies the name of the remote you want to push your code to, and has nothing to do with usernames. The –all switch means push everything. You specify this as git provides functionality to push only parts of a local repo to remote, which is beyond what we are dealing with here.

At this point, a copy of your code should exist in Bitbucket, which you can check via the web interface. You will see that the code has been created under a branch called master. What’s a branch you ask? A good question, and there are as many answers as there are developers. We are only going to be working with the master branch, so its probably better if we leave the topic of branching for another day.

For now, lets just use an analogy: think of your code as a recipe for sourdough bread. One day, you wake up and decide you want to make sourdough bread with black olives. Rather than throw your original recipe (your master branch) in the bin, you make a photocopy of it (your black olive branch), and then make changes to the photocopy, leaving the original in your recipe folder. When you’re happy with your new recipe, you merge the annotations into the original and throw away the photocopy. You have now merged the blackolive branch into the master branch.

Like I say, we only going to deal with the master branch here (think of it has having 2 recipe folders in 2 different houses, and you want to make sure the recipe for sourdough bread is identical in each of the folders). The only other thing to say is that branches exist in your repo regardless of where it is stored, locally or centrally.

So enough about bread and back to git. To be sure we’re on the same page here, you should probably test making further changes to your local code case, and push them to the central repo. Try this:

Edit a file

git commit -am "Computer 1 update" (should report re. your edit)

git push origin master (should ship all your files, with edits, off to your remote).

Again, check the Bitbucket interface to make sure your changes (commits) have been passed in the central repo.

Now, having created a remote repo, a local repo, and mastered the process of moving code changes from the local repo to the remote repo, lets see if we can introduce Computer 2.

Simple stuff first, make sure the git client is installed.

Now, in this case, we must remember that we have already got a git repo, so we are not going to init another one. Instead, we are going to clone the existing git repo from the remote repository. Change to the parent directory where you want to locate the code base on Computer 2. We will allow git to create a new directory at this location to store the code.

sudo git clone https://garrethmcdaid@bitbucket.org/garrethmcdaid/nbfblog.git httpdocs

Hopefully, this command is self-explanatory. We are cloning the nbfblog repo, and its branches, that exists on Bitbucket under the account identifier garrethmcdaid in the new directory httpdocs.

If this command has worked  (again, your Bitbucket password may be required), you should be able to change into the httpdocs directory and view you code.

Now, the real test. Make some changes to the code on Computer 2. The objective here is to make sure those changes are replicated back to Computer 1 via the central repo.

Remember, git is based on local history rather than central history, so when you make a change to code, the first place to commit that is to the local repo. Lets do that now:

git commit -am "Computer 2 update"

That change now exists in the local repo on Computer 2. To get that change into the central repo, lets push it:

git push origin master

That is, push my local history to the master branch in the “origin” remote repo, which git knows is a remote, as the origin repo was cloned from a remote source. To be more precise, you are merging the code in your local master branch to the master branch in the origin remote.

Once again, to verify that this has worked, go back to the Bitbucket web interface and view your source. The changes you made to your code on Computer 2 should now be visible in that source.

Presuming that they are, well done. You have now mastered the core functionality of git, which is actually the hardest part of git to master. To really push the envelope, lets now make sure that when we go back to Computer 1, our code base has the changes we made on Computer 2.

Change back into the directory in which your code was stored on Computer 1. Now, we want to pull the current history of the master branch in the central repo into the master branch of our local repo.

git pull origin master

git knows that origin refers to a remote, because we created remotely, and we’re telling git that we want the history of the master branch, which again is the only branch we are dealing with. Once this command has processed, check your local code case and make sure the changes made on Computer 2 are there.

If they are, well done again. Now, all you have to do is remember the sequence:

Change a file

Commit locally

Push to remote

Pull from remote

Change a file

Commit locally

Push to remote

Pull to remote

as infinitum….

How to strip multiple sections from a string in PHP

Take the following string:

Out in the west Texas town of El Paso
I fell in love with a Mexican girl
Night time would find me in Rosa’s Cantina
Music would play and Felina would whirl

Which is created in raw HTML like this:

Let’s say you want to strip all the sections from this string that are enclosed in boldface tags, including the tags themselves, so that you get this string:

Out in the west Texas town of El Paso
Night time would find me in Rosa’s Cantina

This PHP function will do the job:

function strip_tag_content($string, $start, $end) {

while (true) {
$ini = strpos($string,$start);
if ($ini === false) return $string;
$len = strpos($string,$end,$ini) + strlen($end) – $ini;
$sub = substr($string,$ini,$len);
$string = str_replace($sub,”\n\n”,$string);
}
return $string;

}

Like so:

$s = ‘Out in the west Texas town of El Paso<br /> <b>I fell in love with a Mexican girl</b><br /> Night time would find me in Rosa’s Cantina<br /> <b>Music would play and Felina would whirl</b><br />’;

$s = strip_tag_content($s,’<b>’,'</b>’);

Explanation:

The function accepts the raw string and the tag identifiers as arguments.

It then finds the position of the first letter of the $start argument in the raw string. If no position is found, the raw string is returned in its current state.

If a position is found, the function then calculates the length of the substring that begins at the first letter of the $start argument, and ends at the last letter of the $end argument.

The function then uses the strpos PHP function to create a variable from that substring.

The function then uses the str_replace PHP function to replace that substring with 2 newline characters (or whatever you want to replace it with).

The while wrapper perpetuates this process until no position is found for the $start variable (ie when all instances of the tags have been removed).

So how does this differ from the PHP striptags function?

The standard PHP striptags function will only strip the tags themselves. This function will string the tags and everything between the tags. You can also use this function to strip string parts based on delimiters other than HTML tags.

And now ladies and gentleman, Mr. Marty Robbins:

Facebook Page Tabs and Access Tokens

This is a tricky little issue that has tripped me up a few times and for which I’ve finally found an answer.

If you design a Facebook application, and a Facebook user grants permission to your application to access your data, you can do all sorts of nice things with their friend lists, events, interests, birthday etc.

Your application is allowed obtain that user data on the basis of an access token, which is obtained as follows:

  • You direct the Facebook user to a Facebook URL that describes what data you want access to
  • The Facebook user clicks a link on that Facebook URL to indicate their approval
  • The Facebook user is then redirected back to you application, using a URL that contains a “code” parameter in the GET Request
  • Your application collects that code, sends it back to Facebook, and Facebook responds with a string which is the access token for that user

In this way, Facebook knows that the user in question has allowed your application to access particular data about them.

Now, here’s where it gets a bit more complex.

Facebook allows you to host applications in one of two ways: on a Canvas, or in a Page Tab. Regardless of which you choose, Facebook provides you with a dedicated link for your application as it is presented in either a Canvas or a Page Tab. It is to this URL that the user is generally redirected when Facebook needs to send your application the “code” parameter that your application needs to  request an access token.

However, in the case of both the Canvas and the Page Tab, your application is presented in an IFRAME within the general Facebook skin.

Here, an important difference occurs.

In the case of an application hosted on a Canvas, Facebook will pass on the “code” parameter to the source URL for your application, which is what Facebook uses as the src for the IFRAME. Your application can then pick this up and request the access token.

In the case of an application hosted on a Page Tab, Facebook will not pass on the “code” parameter to the source URL for your application, which means your application cannot request an access token, which means it can’t make requests for user data.

To have your Page Tab hosted application interact with the Facebook API, you need to obtain your access token in a different way.

When Facebook loads your application in the IFRAME, it sends you application a Signed Request, or in other words and encrypted string contain data about the user who is viewing your Page Tab. This tells you thinks like their Facebook ID, if they are an admin of the Page hosting the Page Tab and if they have Liked the Page.

This also contains value named “oauth_token”. Is it this value that you use as your access token when making requests for data for the user who is viewing your application.

Note: to use this, the user still has to have authorised your application to access your data, so you still need to use the Facebook application authorisation process.

You can read more about authentication and Page Tabs at this link, which also links you to a page that tells you how to decode the Signed Request:

https://developers.facebook.com/docs/authentication/pagetab/

Facebook Apps and the Same Origin Policy

Over recent months, Facebook have become a lot stricter in relation to the use of secure URLs for applications presented in the App Canvas and on Page Tabs.

The bottom line in this is that you need to serve your Facebook application content from a secure (https) URL. You can have your app set up to serve on both http and https, but if  you don’t have this https set up correctly, any Facebook user who has Secure Browsing switched on will not be able to use your application.

My reaction to this was to convert all my applications to use https for all connectivity, so as to remove any uncertainty in this regard.

I figured that the users browser would just communicate with my web server over https, regardless of whether the Facebook use was using Secure Browsing or not.

However, there is a big problem with this if you use AJAX calls in your application.

I had set up all my AJAX calls to use https, but if the viewing Facebook user isn’t using Secure Browsing (ie they are connecting to your application over http), you are going to fall foul of Browser restrictions arising from the Same Origin Policy.

This policy is designed to prevent XSS attacks, in that it prevents Javascript from making calls to URLs domains that are not the same as the URL domain the user is viewing. Crucially, this includes the protocol which is used.

That means that if your Facebook user is connecting to http://facebook.nightbluefruit.com for general application content, and the application makes an AJAX call to https://facebook.nightbluefruit.com, the browser will send the request but will refuse to receive the response.

To overcome this, you should really set up your AJAX URLs based on the protocol used to connect to your application. You can use the $_SERVER['HTTPS'] special variable to do this.

Adding text to images to promote your site

Promoting a new website is always difficult, and you really need to give yourself every advantage possible if you want to get it out there.

One technique that I don’t see used very often is writing the name of your website on any images that are uploaded to it. When you do this, and your images are picked up by Google, and then used by others when they find them in an Images search, your website gets a free plug.

Writing on images isn’t very difficult at all. Most PHP installations will have GD, and after that, all you need is a TTF font file and the imagettftext PHP function. Basically you just pass your image resource through the function and it comes out the the other end with text on top.

I’m trying to promote the following site at the moment:

Minifigure Mix

which is all about Lego Minifigures.

All of the image filenames contain the words ‘lego’ and ‘minifigure’ and each image has ‘minifiguremix.com’ written on the top left hand corner.

How to update a Facebook Fan Page from PHP

Note: Facebook changes its API as frequently as you change your socks. These instructions worked as of Apr 19th 2011.

In a previous post, I outlined how to update your Facebook Profile from a PHP script.

This is fine if you are using Facebook as an individual, but if you are a business or an organisation, you won’t have a profile, you will have a Fan Page, which people ‘Like’.

Updating a Fan Page from a PHP script is a lot more difficult, because Fan pages are managed by users with standard profile accounts, and you need to obtain a extended range of permissions in order make updates to their Pages.

Anyway, its is possible, and here’s how.

Firstly, this is what you will need:

A proper browser (ie anything other than Internet Explorer) that you can be confident will send long HTTP GET requests

cURL, which can be run from a command line (for testing)

A good text editor

A credit card (weird, I know, but go with it)

A standard Facebook account

Overview

We are going to create a Facebook Application, and add that Application to the Facebook User Account/Profile which manages the Page we want to update. The Application will have the necessary permissions to update Pages which the Facebook User Account/Profile manages.

Step 1: Add the Facebook Developer Application to your Facebook Account

Login to Facebook

(If you have added the Facebook Developer application previously, you can skip this bit)

Go to: http://www.facebook.com/developers/

Look for the button that allows you to add the Facebook Developer Application

If you haven’t added this before, you will need to confirm your identity. You may be able to do this with your mobile phone, but if not you will have to enter valid Credit Details. No charge will be made to your Credit Card.

Step 2: Create an Application

Once the Facebook Developer Application is added, you now create an Application. Call it something relevant. You don’t need to enter much in the way of detail for the application. The only important data you need to enter is under Website, where you should enter a Site URL and Site Domain.

These should be something relevant, for instance, the website address of the business/organisation to whom the page relates. Note: enter a trailing slash for the Site URL eg http://www.mysite.com/
Now, save the details, and you will be returned to a summary page which lists the details for your application. You do not need to submit your application to the Facebook Directory.

From this page, copy and paste your Application ID and Application Secret into your text editor

Step 3: Establish access to your Account/Profile for your Application

Starts to get a bit tricky now, so pay attention. Read everything twice.

You now what to obtain an Authorisation Code for your Application. This code will be generated by Facebook based on the permissions your Application requests from your Facebook User Account/Profile when you add your Application to your Faecbook Account/Profile.

Construct the following URL in your text editor:

https://www.facebook.com/dialog/oauth?client_id=<YOUR APPLICATION ID>&redirect_uri=<YOUR SITE URL>&scope=manage_pages,offline_access,publish_stream

YOUR APPLICATION ID = Application ID you took from your Application Details

YOUR SITE URL = The Site URL you entered when setting up your Application

scope = The permissions you are requesting:

manage_pages = allows application to manage pages for which the user is the administrator

offline_access = allows updates to occur indefinitely

publish_stream = allows application to update the feed of the pages for which the user is administrator

Now, ensuring that you are logged into Facebook, paste the URL into your browser and hit enter.

A Facebook page will render, prompting you to add the application with the permissions as described above. Accept this, and you will be redirected to your Site URL. The actual query string to which you are re-directed will contain a long ‘code’ value. Copy this from your browser address bar and paste into your text editor.

This code is your Authorisation Code.

Step 4: Get an Access Token to allow your Application access your Profile

Now that you have an Authorisation Code, which is a sort of once off thing, you can request an Access Token, which will allow your Application have permanent access to your User Profile.

Again in your text editor, construct the following URL:

https://graph.facebook.com/oauth/access_token?client_id=<YOUR APPLICATION ID>&redirect_uri=<YOUR SITE URL, WITH A TRAILING SLASH>&client_secret=<YOUR APPLICATION SECRET>&code=<YOUR AUTHORISATION CODE>

Be extra careful with this. Its a very long string. Ensure you include a trailing slash in your Site URL.

Now, paste the URL into your browser and hit enter. Facebook should return a single line like:

access_token=220088774674094|c7cb68d51ae2f40e9878ab14.xxxxxxxxxx etc etc

(Note: this is not a real access token, its one I made up.)

You now have an Access Token that allows your Application do stuff to your User Profile

Step 5: Get an Access Token for the Page you want to update

Yes, more Access Tokens are needed! You need a specific Access Token for each Page you want to update! Jesus wept!

Construct the following URL in your text editor:

https://graph.facebook.com/me/accounts?access_token=<YOUR ACCESS TOKEN FOR YOUR USER PROFILE>

Paste it into your browser and hit enter. Facebook will now return JSON objects for each of the Pages and Applications that are under your User Profile. You should see an object for the Page you want to update, each of which will include an ‘id’ and ‘access_token’.

Copy and paste these into your text editor.

You now have an Access Token and Page ID for the Page you want to update.

Step 6: Test!

Finally!

Construct the following command in your text editor:

curl -F ‘access_token=<THE ACCESS TOKEN FOR THE PAGE YOU WANT TO UPDATE’ -F ‘message=It works.’ https://graph.facebook.com/<THE ID FOR THE PAGE YOU WANT TO UPDATE>/feed

Paste to a command line and hit enter. If it works, you will get back a JSON object containing an update id, and the message will appear on the Feed of the Facebook Page.

If not, you will get some class of error. Retrace and try again. I can’t emphasis enough how unforgiving the tolerances are here, but if you persist, it will work!

Once you have it working, you can then build the update into your PHP application using cURL.

More here:

http://developers.facebook.com/docs/authentication/
http://developers.facebook.com/docs/reference/api/

The pain of Drupal

I’ve recently taken on a job that requires modification of a web site built on Drupal, and 3 days in, I feel like I need a 2 week holiday.

Drupal, and its counterpart, Joomla, are Open Source Content Management systems. The idea is that the allow people who don’t know anything about HTML, PHP, Javascript etc etc to build complex, feature rich websites.

Their use on the web has exploded over recent years, as more and more would be ‘web designers’ have started using them as their framework for building websites.

This in turn as led to the development of lots and lots of Drupal plugins and widgets, which add a futher layer of fudge and complexity to something that is already very fudgy and very complex.

Under the hood, its a morass.

Before starting work on the modifications I had to make, I took a look at the MySQL database on which is runs. It had 288 tables (my own CMS has 12 tables, and even poor old WordPress only has about 40 tables).

If that wasn’t bad enough, when I then tried to run a local copy of the website on my laptop, I started to get errors about PHP not having enough memory to run the Drupal scripts. PHP is normally allocated about 16MB of memory as part of its installation; to run Drupal, I had to up this to 64MB!!

Its gets worse. Looking at the raw HTML generated by Drupal, I saw that it was loading 25 different CSS files, and 14 different Javascript files! And when I examined the DOM via Firebug, I could see that certain elements were taking CSS properties from up to 4 different files!

All this was bad enough, but it was nothing comparred to actually using the management interface to build content. The admin menu in Drupal has 14 different options, and each of these has a plethora of sub options, all of which refer to vague concepts like Blocks, Views, Modules, Panels, Stories etc (they also refer to a Page, but its isn’t really clear what a Page is).

My first thought was that it would be actually easier to learn HTML, PHP and Javascript than try and unravel this crap.

I persevered anyway. I made a view changes to pages where I could figure how to make those changes, but none of them appeared on the actual website. This was most probably to do with caching I thought, but there was nothing in the Drupal interface that said ‘You should clear your cache to see these changes’. I also thought  it was quite odd that an app that generates links to 40 odd CSS and Javascript files should be worried about caching.

I looked around for somewhere I could clear the cache, but could find nothing. I eventually googled the subject and found that the clear cache was a sub sub option under the ‘Site Configuration’ menu option.

On another occasion, I had to change some User Permissions. When I clicked on the Save button, my laptop started to grind to the extent that I thought it was going to shut itself down to prevent an explosion.

Perhaps my most stressful experience with Drupal was dealing with this bug. There are 300 posts on the Drupal Forum thread on this bug, and the upshot of it isn’t there isn’t a universal solution. You basically have to figure out what version of a few different modules you are using, and then apply a serious of patches which may or may not break other parts of your installation.

Lets try and use an analogy here.

Building a website with Drupal is like trying to build a house by joining together five or six mobile homes. Its cheap, it doesn’t take long to put together and it seems like a easy solution to a pressing problem.

What you get is something that is about the same size as a house, and that has certain features of house (eg windows and doors), but that also has 5 bathrooms, 5 kitchens, no corridors and no rooms of any useful size. You also need 5 different electricty meters, and in certain cases, if you want to walk from one room to another, you have to leave house and come in through another door.

Also, if you want to make even minor modifications to the look of your house  in future, you have to take the whole thing apart and stick it back together again.

Don’t get me wrong. Open source packages like Drupal are essential part of the Internet, but its becoming clear that the more an application tries to be a solution for everything, the more likely it is to become a solution for nothing.

Refreshing an image when filename is the same

Here’s a nifty little trick that might get you out of a bind:

Say you have a web app in which the user can change the images by uploading new image files. Say then that the application requires that the image filename remain the same. See the problem?

The image may have changed but your browser is still looking at the same filename, so it will display its cached image. Of course, you could try an edit your HTML to that caching doesn’t occur, but we like caching, so here’s a better solution.

An image file, like a script file, can accept an argument when requested with HTTP. For instance, the image below is requested so:

<IMG src=/blog/wp-content/pottery-main.thumbnail.jpg?foo>

The cool thing about this is that you attach random arguments to your image calls, either in HTML or in Javascript, which will cause the browser to reload that image every time it is called. Hence, when your user loads a new image, and this image has the same file name as the old image, this method will allow the user to view the new image without having to do a manual refresh.

In Javascript, you can create a random argument using time and date functions. e.g.

my_image.src=”images/pottery.jpg?” + (new Date()).getTime();

or

image_td.innerHTML = “<IMG src=images/pottery.jpg?” + (new Date()).getTime() + “</IMG>”;

Managing images with GD

One of the biggest problems I find with Content Management Systems is that while users are capable of managing web site text, the results are a little less predictable when it comes to managing images.

There are 2 primary problems:

Firstly, a lot of users aren’t comfortable with scaling images to fit into the spaces designed for them, and secondly, if you allow for this and use the IMG tag to scale the height and width of the image, you get fuzzy distorted images and large files that take an age to load in the browser.

This is why programatically manipulating uploaded images is such a good idea.

There are 2 tools you can use to manipulate images in PHP: GD or ImageMagick

GD is more commonly found in PHP compiles, and ImageMagick can be difficult to install correctly, so lets stick with GD for this discussion.

The problem I faced was this:

I wanted users to be able to upload long images, tall images and square images, but I wanted these to fit into a space 214px x 214px on a website page without having to use the IMG height and width tags.

This meant a 2 step process for the long and tall images: first, resize them so that they were with 214px tall or wide, and then crop them so that they were both 214px tall and 214px wide. I also wanted to make sure I was cropping down to the middle portion of the image, so that I was getting what the user wanted to appear and not the top, bottom or side of the image. The task for square images was a little simpler, in that I only had to resize the image (no cropping).

The PHP function I created is produced here. I’ve added inline comments to explain.

<?php

#Arguments = source image file, altered image file, required dimesions of altered image

function resize_image($src_image,$dst_image,$xsize,$ysize)
{

list($w,$h) = getimagesize($src_image);

#Deals with images that are wider than they are tall

if ($w > $h) {

#First, resize the image so that 1 side is the required length
$new_height = $ysize;
$new_width = ($ysize / $h) * $w;

$x=$w;
$y=$h;

#Resized temp image

$temp_image = “images/” . date(“U”) . “.jpg”;

$image = imagecreatefromjpeg($src_image);
$crop = imagecreatetruecolor($new_width,$new_height);
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
imagejpeg($crop,$temp_image,100);

# Now use temp image to create final image

list($w,$h) = getimagesize($temp_image);

if ($h >= $ysize) $new_height = $ysize;
if ($h <= $ysize) $new_height = $h;
$new_width = $ysize;

#This bit sets the dimensions for the middle of the image
$x = ($w – $ysize) / 2;
$y = 0;

$image = imagecreatefromjpeg($temp_image);
$crop = imagecreatetruecolor($new_width,$new_height);
imagecopy ($crop, $image, 0, 0, $x, $y, $new_width, $new_height);

#As above but for images that are taller than they are wide

} elseif ($h > $w) {

$new_width = $xsize;
$new_height = ($xsize / $w) * $h;

$x=$w;
$y=$h;

$temp_image = “images/shops/” . date(“U”) . “.jpg”;

$image = imagecreatefromjpeg($src_image);
$crop = imagecreatetruecolor($new_width,$new_height);
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
imagejpeg($crop,$temp_image,100);

list($w,$h) = getimagesize($temp_image);

if ($w >= $xsize) $new_width = $xsize;
if ($w <= $xsize) $new_width = $w;
$new_height = $xsize;
$y = ($h – $xsize) / 2;
$x = 0;

$image = imagecreatefromjpeg($temp_image);
$crop = imagecreatetruecolor($new_width,$new_height);
imagecopy ($crop, $image, 0, 0, $x, $y, $new_width, $new_height);

#Square image; no need for cropping
} elseif ($h == $w) {

$new_width = $xsize;
$new_height = $ysize;

$x=$w;
$y=$h;

$image = imagecreatefromjpeg($src_image);
$crop = imagecreatetruecolor($new_width,$new_height);
imagecopyresized ($crop, $image, 0, 0, 0, 0, $new_width, $new_height, $w, $h);

}

#Save the new images and discard any temporary images
imagejpeg($crop,$dst_image,100);
imagedestroy($image);
}

?>

Here’s an example:

This is the original image resized with IMG tags:

pottery-main.jpg

And here is the programatically manipulated image without any IMG tags:

v1-53.jpg