phpThumb helper for CakePHP

Here is a simple phpThumb helper for CakePHP. The helper will check to see if a thumbnail is cached first. If its not, it will instantiate a phpThumb object, process the image and cache it for you.

The cache filename is based on the parameters you pass in. So for example, a 400x300 thumb would yield a different cache filename than the same image at 200x200. I also added a check to see if the source file has been modified since the thumb was last created. This will generate a new thumbnail for the updated image automatically. You should be able to do anything that phpThumb can do with this helper. Cropping, watermarks, etc.

Enjoy... And thanks to the people on the bakery who found it useful and submitted positive comments when I submitted the first version back in July 2008.

Installation

Get a copy of phpThumb

Download a copy of phpThumb and place it in your Vendors directory.

Note: I renamed the phpThumb folder from "phpThumb_1.7.9" to just "phpThumb". If you plan to keep the default folder name, just change the import statement in the helper.

Get the helper code

Grab the helper code from GitHub and place it in the app/views/helpers directory.

Usage

Here's a quick explanation of the options you can pass in:

save_path - Where to save the thumbnail. (Make sure it is writable by the web server)

display_path - The web accessible path to the directory that the thumbnail lives in after its created. I included this so instead of using /path/to/image/directory, I can also use http://images.domain.com if I wanted to. (Although I don't do it that way in this blog);

error_image_path - The default image to display if something goes wrong while generating a thumbnail.

src - The source image to be converted into a thumbnail.

Below is the code I use to generate square thumbnails for my archive pages.

	
<? $thumbnail = $phpthumb->generate( array( 'save_path' => WWW_ROOT . 'assets/img/thumbs', 'display_path' => '/assets/img/thumbs', 'error_image_path' => '/assets/img/error.jpg', 'src' => WWW_ROOT . 'assets/img/' . $article['Article']['thumbnail'], // From here on out, you can pass any standard phpThumb parameters 'w' => 100, 'h' => 100, 'q' => 100, 'zc' => 1 ) ); ?> <?= $html->image($thumbnail['src'], array('width' => $thumbnail['w'], 'height' => $thumbnail['h'])); ?>

If all goes well, the helper will return an array like so:

Array
(
	[error] => 0 // No error, everything went ok
	[src] => /assets/img/thumbs/911229ce463571caf1411512c866e05a.png // Path to thumbnail
	[w] => 100 // width
	[h] => 100 // height
)

If an error occurs, you get something like below:

Array
(
	[error] => 1 // There was an error
	[error_detail] => File dd does not exist // The error message
	[src] => /assets/img/error.jpg // Display the default or error image
	[w] => 100 // width
	[h] => 100 // height
)

Comments (10)

One small tip on the cache file name creation. If you look at the directory sub-structure that phpThumb actually uses when generating thumbnails on the fly you'll see that it breaks images up into multiple sub-directories like /temp/a/c/3/<cachefilename>.jpg.

The reason for this is that dumping everything into a single directory can actually produce a serious performance hit later on. I've see directories that a simple 'ls' call would take over 15 minutes to complete for this exact reason.

I'd recommend taking the 1st 3 or 4 digits of the generated md5 and use each of them as a directory in the cache path to avoid the issue. Outside of that, your code's been a huge help. Thank you!
Thanks for the feedback Barry. I'll work on adding support for cache sub-directories this weekend.
Hi, I'm trying to use this and I keep getting the error:
The image “http://localhost/~Hooman/caroverload/garage_car/126” cannot be displayed, because it contains errors.

When I call your first snippet of code in my garage_car/126 view page it tries to turn the whole page into a png. I'm a bit confused what's going on if you're able to help thanks!
I've been trying to do this for awhile and finally I got it working, thanks to your helper. Thanks so much for your work.
Thanks Matt.
First of all this is a great start on what could be an amazing helper, keep up the good work!

I want to use this in a site where multiple organisations have their own articles with images. I am using preg to find the first image src value within the body of each article and then creating a thumbnail to be used when listing articles.

I want to save the thumbs to be cached in /assets/organisations/:org_id/img/thumb, but whilst your helper allows me to specify the directories I want, it will not actually create directories on the fly. I would imagine this is a simple thing, but beyond me at present.

The other problem I am having is that I have had to remove the is_file() and filectime() checks as they stop the use of PHPThumbs remote src features and some of our articles do display images from remote sites.

Thanks,

Paul.
Paul,

You should probably note that removing the call to is_file() will bypass the caching. So the thumbnail will be regenerated every time the page is loaded. Did you try just removing the filectime() function? That should be the only one you would need to remove. Let me know if that works for you.

On a side note I have been meaning to update this helper. I will try to incorporate your suggestions and Barry's as well. When I wrote this helper I never accounted for the scenario of images being loaded via http. So yeah, you might run into some problems in that regard.
I must admit I want to keep caching if possible, but is_file() checks for validity of local file paths only and as such stops you using PhpThumb's ability to work with remote images.

I was working on this pretty late last night and only just started work this morning, so I am sure sometime today I can come up with some half-way solution which works perfectly based on your helper.
Paul,

You're right, I just realized there are two references to is_file() in the code. If you removed the one in the validate() function everything should be okay. If you remove the reference in the image_is_cached() function, you will lose caching. Sorry if I misunderstood. In that case, everything should be fine.
@Dan: I eventually got around to working with this again and at face value I'm pretty happy with the results.

I'm still using your helper, albeit a little modified, but I'm taking a very different approach to creating the thumbnails. I reckon that to save on resources the thumbnails can be generated at the time of adding an article and then the src and alt of those thumbs can be stored in the dbase.

I am using TinyMCE with ImageManager so users can include one or more local or remote images in the body of their article. I have an afterSave() function in my Article model which uses a preg_match to find the first image in the body and then a preg_match_all to pull that image tag apart so I have access to it's src and alt values.

If an img tag is found the function imports your modified helper (and I know this is wrong, but it works for now) and creates two thumbs, one small one to be used in my indexes, and one larger one to be used for featured articles. It then saves the thumb src's along with the images alt values in the database.

My modifications to your helper include:
1. Commenting out the first check in the validate method to allow for remote files to be used
2. Removing line 41 from set_cache_filename() as filectime() again only works for local files, and removed $last_modified from line 43.
3. My main change was to include the below code at line 41:

// check for existance of save path, creating directories if required
$Folder = new Folder();
$slash = $Folder->correctSlashFor($this->options['save_path']);
$this->options['save_path'] = str_replace(array('\\', '/'), $slash, $this->options['save_path']);
$path = explode($slash, str_replace(WWW_ROOT, '', $this->options['save_path']));
foreach($path AS $dir) {
$buildPath[] = $dir;
if(!is_file(WWW_ROOT.join($slash, $buildPath))) {
$Folder->create(WWW_ROOT.join($slash, $buildPath));
}
}

This imports CakePHP's Folder object from the core and checks for the existence of all parts of the specified save_path. Any directories not existing are created so every thumb can have a different path without worrying about the need to create that path, great for sites with user profiles where you want to keep each users thumbs separated.

Will keep you updated on how my solution holds up as the site is to be launched in the coming weeks and it should get a lot of interest.

Paul.

Leave a comment

Name (Required)
Email (Required)
Url (Optional)
Comment (Required)