views:

134

answers:

3

Hello everyone,

This is an architecture question, but its solution lies in ColdFusion and MySQL structure--or at least I believe so.

I have a products table in my database, and each product can have any number of screen-shots. My current method to display product screen-shots is the following:

I have a single folder where all screen-shots associated with all products are contained. All screen-shots are named exactly the same as their productID in the database, plus a prefix.

For example: Screen-shots of a product whose productID is 15 are found in the folder images, with the name 15_screen1.jpg, 15_screen2.jpg, etc...

In my ColdFusion page I have hard-coded the image path into the HTML (images/); the image name is broken into two parts; part one is dynamically generated using the productID from the query; and part two is a prefix, and is hard-coded. For example:

<img src"/images/#QueryName.productID#_screen1.jpg">
<img src"/images/#QueryName.productID#_screen2.jpg"> etc...

This method works, but it has several limitations the biggest listed bellow:

  1. I have to hard-code the exact number of screen-shots in my HTML template. This means the number of screen shots I can display will always be the same. This does not work if one product has 10 screen shots, and another has 5.
  2. I have to hard-code image prefixes into my HTML. For example, I can have up to five types of screen-shots associated with one product: productID=15 may have 15_screen1.jpg, 15_screen2.jpg, and 15_FrontCover.jpg, 15_BackCover.jpg, and 15_Backthumb.jpg, etc...

I thought about creating a paths column in my products table, but that meant creating several hundreds of folders for each product, something that also does not seem efficient.

Does anyone have any suggestions or ideas on the correct method to approach this problem?

Many thanks!

+2  A: 

How about...

use an Image table, one product to many images (with optional sortOrder column?), and use imageID as the jpeg file name?

update:

Have a ImageClass table, many Image to one ImageClass.

Image
-----
ID
productID
imageClassID (FK to ImageClass)

Use back-end business logic to enforce the some classes can only have one image.

Or... if you really want to enforce some classes can only one image, then can go for a more complex design:

Product
------
ID
name
...
frontCoverImageID
backCoverImageID
frontThumbImageID
backThumbImageID

Image
-----
ID
productID
isScreenShot (bit)    // optional, but easier to query later...

However, I like the first one better since you can have as many classes you see fit later, without refactoring the DB.

Henry
For ease, we ususally did something like http://domain/images/{productid}/{imageid}.png (we settled on one image type per project). Adding the productID to the path makes it easy to go look at what images you have for that product, and make sure it is displaying correctly.
Ben Doom
Thanks Henry. I think the method you suggested would suit me fine if I were using the same type of image (screen-shots). However, if I have different image classes, I'm not sure how to go about utilizing your suggested method usefully. For example, I have 5 classes of images and each class has a different placement on the page: Front and back cover, Front and back thumbs, and screen-shots. Screen-shots would have multiple images, while the other 4 classes will only have one. Could you please elaborate on how I can implement your suggestion in this usage case? Many thanks.
Mel
see edited answer.
Henry
Thanks, Henry. I'll be trying out your suggestion.
Mel
+1  A: 

Keeping information on how many and what images in the database is definitely the way to go.

Barring that, if you want to use naming conventions to associate images with products, and the number of images is arbitrary, then it's probably a better idea to create one folder per product:

/images/products/{SKU1}/frontview.jpg
/images/products/{SKU1}/sideview.jpg
/images/products/{SKU2}/frontview.jpg

and so forth. Then use <cfdirectory> to collect the images for a given product. You might also want to name your images 00_frontview.jpg, 01_sideview.jpg and such so that you can sort and control what order they'll display on the page.

MightyE
Thanks for the suggestion. I would like to go with the suggestion Herny gave, but as I just commented, I'm not sure how to implement it if I have different image classes (front and back covers, front and back thumbs, and screen-shots; screen-shots can have multiple images). Any thoughts? Many thanks.
Mel
A simple solution is to have a product_images table something like: | image_id | product_id | image_type | image_name | path | | 1 | 'abc-123' | 'front-cover' | "Front Cover 1" | "images/product/cover1.png" || 2 | 'abc-123' | 'front-cover' | "Front Cover 2 | "images/product/cover2.png" || 3 | 'abc-123' | 'back-cover' | "Back Cover" | "images/product/back1.png" |And so on. This is a *simple* way to do it, but not a well-normalized database (so if you have a few thousand images you would get better performance to normalize it first).
MightyE
+1  A: 

use the cfdirectory tags to inspect the filesystem:

<!--- get a query resultset of images in filesystem --->
<cfdirectory action="list" name="images" directory="images">

<!--- get images for specific product --->
<cfquery name="productImages" dbtype="query">
select *
from images
where name like '#productid#%'
</cfquery>

<cfoutput query="productImages">
    <img src="#productimages.directory#/#productimages.name#" />
</cfoutput>

You could even try using the filter attribute to cfdirectory to try and omit the QoQ

Antony
Thanks, Antony! I'm curious: Would this method be best practice if the directory contains about 4,000 images? Would it not take consider resources for <cfdirectory> to scan a directory this size?
Mel
@mel - i don't think it would be too bad. It's easy to test and if you find that it does take too many resources you can always save the results into the application scope and refresh that list as appropriate
Antony