views:

68

answers:

5

Here's a bit of history first: Recently finished an application that allows me to upload images and store them in a directory, it also stores the information of that file in a database. Database stores the location, name and gives it an ID (auto_increment).

Okay, so what I'm doing now is allowing people to insert images into posts. Throwing a few ideas around on the best way to do this, as the application I designed allows people to move files around, and I don't want images in posts to break if an image is moved to a different directory (hence the storing of IDs).

What I'm thinking of doing is when linking to images, instead of linking to the file directly, I link it like so:

<img src="/path/to/functions.php?method=media&id=<IMG_ID_HERE>" alt="" />

So it takes the ID, searches the database, then from there determines the mime type and what not, then spits out the image.

So really, my question is: Is this the most efficient way? Note that on a single page there could be from 3 to 30 images, all making a call to this function.

+1  A: 

Normally, I would recommend keeping the src of an image static (instead of a php script). But if you're allowing users to move them around the filesystem you need a way to track them

Some form of caching would help reduce the number of database calls required to fetch the filesystem location of each image. Should be pretty easy to put an indefinite TTL on the cache and invalidate upon the image being moved.

Mike B
So what would you suggest? I've never done any kind of caching before. To me, if their are 30 different images on the one page, caching isn't going to help since it needs to call the database 30 times. Unless, in my application I load ALL the images in the database and store them in an array which is accessible by functions.php (I'm running this on my own MVC, so making it available won't be a problem). That way, instead of making so many database calls, it just makes one. Then it can just access the array. Would that be more or less efficient, keeping in mind their could be a lot of images.
Jason Lewis
Technically, it doesn't need to call the database 30 times if you use an `IN` query rather than an `=` query.
Hammerite
How could you use IN for something like this? Since each image will have it's own link to functions.php, really, they will each be calling the function separately. Right?
Jason Lewis
+1  A: 

I don't think you should worry about that, what you have planned sounds fine.

But if you want to go out of your way to minimise requests or whatever, you could instead do the following: when someone embeds an image in a post, replace the anchor tag with some special character sequence, like [MYIMAGE=1234] or something. Then when a page with one or more posts is viewed, search through all the posts to find all the [MYIMAGE=] sequences, query the database to get all of the images' locations, and then output the posts with the [MYIMAGE=] sequences replaced with the appropriate anchor tags. You might or might not want to make sure users cannot directly add [MYIMAGE=] tags to their submitted content.

Hammerite
I was thinking along those lines as well, put yes, it could potentially allow the end-user to place in false image tags, thus breaking the application (although it would be their fault).
Jason Lewis
How would your current <img /> tag method be any different?
Joel L
I suppose there isn't any difference, except it would be far easier using the <img /> tag method. Less hassle.
Jason Lewis
+2  A: 

Doing that should be fine as long as you are aware of your memory limitations configured by both PHP and the web server. (Though you'll run into those problems merely by receiving the file first)

Otherwise, if you're strict about this being just for images, it could prove more efficient to go with Mike B's approach. Design a static area and just drop the images off in there, and record those locations in the records for their associated post. It's less work, and less to worry about... and I'm willing to bet your web server is better at serving files than most developer's custom application code will be.

andyortlieb
A: 

The way you have suggested will work, and it's arguably the nicest solution, but I should warn you that I've tried something similar before and it completely fell apart under load. The database seemed to be keeping up, but the script would start to time out and the image wouldn't arrive. That was probably down to some particular server configuration, but it's worth bearing in mind.

Depending on how much access you have to the server it's running on, you could just create a symlink whenever the user moves a file. It's a little messy but it'll be fast and reliable, and will also handle collisions if a user moves a file to where another one used to be.

Andy
It'll be on a shared hosting account. Never done a symlink before, so I'm not sure if it could help me.
Jason Lewis
A: 

Use the format proposed by Hammerite, and use [MYIMAGE=1234] tags (or something similar).

You can then fetch the id-path mappings before display, and replace the [MYIMAGE] tags with proper tags which link to images directly. This will yield much better performance than outputting images using php.

You could even bypass the database completely, and simply use image paths like (for example) /images/hash(IMAGEID).jpg. (If there are different file formats, use [MYIMAGE=1234.png], so you can append png/jpg/whatever without a database call)

If the need arises to change the image locations, output method, or anything else, you only need to change the method where [MYIMAGE] tags are converted to full file paths.

Joel L