Jump to content

Recommended Posts

The objective is to add a random number to the end of rotating images in a PHP array to prevent browsers from caching the image. The number should be appended to the end of the image URL I have the array, and it works great. I have a random number generator, and that works. I'm doing something wrong when using PHP to apply a random number to the links in the array.

 
Here is the array sample which contains link and image:
 
    <?php
    $content1 = '<a href="http://example.net" title="Example 1" target="_blank"><img src="http://example.com/gallery/image-1.png" alt="Image 1" width="300" height="250" class="gallery-image"></a>';
    $content2 = '<a href="http://example.net" title="Example 2" target="_blank"><img src="http://example.com/gallery/image-2.png" alt="Image 2" width="300" height="250" class="gallery-image"></a>';
    $content3 = '<a href="http://example.net" title="Example 3" target="_blank"><img src="http://example.com/gallery/image-3.png" alt="Image 3" width="300" height="250" class="gallery-image"></a>';
    $content4 = '<a href="http://example.net" title="Example 4" target="_blank"><img src="http://example.com/gallery/image-3.png" alt="Image 4" width="300" height="250" class="gallery-image"></a>';
    $content = array($content1, $content2, $content3, $content4,);
    shuffle($content);
    ?>
    <?php print $content[0] ?>
 
This is the random number generator:
 
    <?php echo rand() . "\n"; ?>
 
What I want should look like this:
 
    $content1 = '<a href="http://example.net" title="Example 1" target="_blank"><img src="http://example.com/gallery/image-1.png?29384756" alt="Image 1" width="300" height="250" class="gallery-image"></a>';
 
I've attempted to put the random number generator in the array's text string, but I'm doing something wrong, as either it won't generate a number, or the PHP code displays within the HTML, so I'm unsure of how the random number would generate within the array HTML text.
 
Again, the objective is to add a random number query string to the end of the image URL so the array still displays the image and prevents a browser from caching the image when/if a page is refreshed.
 
I'm not sure how or if the random number generator can be placed into the array's text and image URL. Any better way of doing this?

Why do you even want to prevent caching altogether? If you merely need the ability to change the images behind the URLs, simply store a version number for each image and append it to the URL:

https://www.yoursite.com/gallery/image-1.png?v6

Then you won't be wasting traffic for data which can be cached.

Why do you even want to prevent caching altogether? If you merely need the ability to change the images behind the URLs, simply store a version number for each image and append it to the URL:

https://www.yoursite.com/gallery/image-1.png?v6

Then you won't be wasting traffic for data which can be cached.

 

 

Actually, I do not want browsers to cache the images in the array, hence the problem. The problem with a version number is that it doesn't change automatically, so the browser caches it anyway. I've tried a few .htaccess tricks to 'prevent' browser caching, including a '1 seconds' but browsers mostly ignore the header settings.

 

So, what I want is a new 'version number' in the query string with every hit so the images will rotate appropriately but NOT be cached by the browser. That's important in this case.

You're trying to fix the symptom. Fix the actual problem: your server is telling browsers to cache the images.

 

Is this all online somewhere we can see?

 

That's another issue because browsers do not obey the .htaccess headers the same way. Even using .htaccess to set image caching at x-seconds does not always work, particularly in Chrome, but Safari, Firefox, too, and don't get me started on IE. There won't be many images in the rotation but each one needs NOT to be cached, hence the desire to have a version or string appended to the image URL.

1.

 

That's another issue because browsers do not obey the .htaccess headers the same way.

Then you aren't using the right directives. It's true that browser's don't have to obey the settings, but when done correctly they will obey the headers when they are supposed to.

 

2. If each image in the list corresponds to one unique image then you do want the images cached. What you don't want is the HTML producing the random image to be cached. Which is entirely different than what you're going at. And it shouldn't even happen in the first place with PHP scripts. Which leads me to

 

3. Have you confirmed that there is an actual problem here? Or do you think/assume there is a caching problem and you're trying to fix it preemptively?

1.

 

Then you aren't using the right directives. It's true that browser's don't have to obey the settings, but when done correctly they will obey the headers when they are supposed to.

 

2. If each image in the list corresponds to one unique image then you do want the images cached. What you don't want is the HTML producing the random image to be cached. Which is entirely different than what you're going at. And it shouldn't even happen in the first place with PHP scripts. Which leads me to

 

3. Have you confirmed that there is an actual problem here? Or do you think/assume there is a caching problem and you're trying to fix it preemptively?

1 - Yes, the right directives are used in .htaccess (there are many; tried them all). Not ALL browsers obey the directives. That's fact. And that's part of the problem.

 

2 - No, I do not want the images cached. Period. With every page reload I want a new or different image displayed.

 

3 - Yep. Caching is a problem. I do NOT want the images cached. .htaccess and directives do NOT always work. A version query string does.

 

So, back to the original question; how can a random number be inserted as a version at the end of the images in the array?

IMHO - the src attribute is pointing to a file. It does not go thru any kind of process to determine your query string appendage. When your php script builds that link it has to set the src attribute (using a random routine) to the actual filename to be displayed.

The point of the query is to “fake” a new URL so that the browser won't use cached data. From the browser's perspective, /some/file?foo and /some/file?bar are two different entities, even when the query doesn't actually do anything.

 

I'm fairly sure none of this makes any sense in the concrete case, but the OP insists on it.

1 - Yes, the right directives are used in .htaccess (there are many; tried them all). Not ALL browsers obey the directives. That's fact. And that's part of the problem.

What are you using? Expires? Expires sucks. How about ETags? ETags are more-or-less perfect, provided the backing information is chosen well (defaults are normally fine).

 

2 - No, I do not want the images cached. Period. With every page reload I want a new or different image displayed.

We're saying two different things. But I've tried to get us on the same wavelength and that isn't working, so I'm bowing out of this argument.

 

3 - Yep. Caching is a problem. I do NOT want the images cached. .htaccess and directives do NOT always work. A version query string does.

I stand by my "not using the right directives" comment. And see above replies.

 

So, back to the original question; how can a random number be inserted as a version at the end of the images in the array?

A random number is more than you need. The time is sufficient.

<?php
    $time = time();
    $content1 = '<a href="http://example.net" title="Example 1" target="_blank"><img src="http://example.com/gallery/image-1.png?' . $time . '" alt="Image 1" width="300" height="250" class="gallery-image"></a>';
    $content2 = '<a href="http://example.net" title="Example 2" target="_blank"><img src="http://example.com/gallery/image-2.png?' . $time . '" alt="Image 2" width="300" height="250" class="gallery-image"></a>';
    $content3 = '<a href="http://example.net" title="Example 3" target="_blank"><img src="http://example.com/gallery/image-3.png?' . $time . '" alt="Image 3" width="300" height="250" class="gallery-image"></a>';
    $content4 = '<a href="http://example.net" title="Example 4" target="_blank"><img src="http://example.com/gallery/image-3.png?' . $time . '" alt="Image 4" width="300" height="250" class="gallery-image"></a>';
    $content = array($content1, $content2, $content3, $content4,);
    shuffle($content);
    ?>
    <?php print $content[0] ?>

IMHO - the src attribute is pointing to a file. It does not go thru any kind of process to determine your query string appendage. When your php script builds that link it has to set the src attribute (using a random routine) to the actual filename to be displayed.

 

Thanks. Not sure I follow that to a solution. The array contains the link to the image. I'm trying to find a way to get a version/query string appended to the end of the image link. The array handles the rotation of the images, but the version/query string is needed to break the caching problems. Browsers don't agree or obey htaccess directives with any consistency.

The point of the query is to “fake” a new URL so that the browser won't use cached data. From the browser's perspective, /some/file?foo and /some/file?bar are two different entities, even when the query doesn't actually do anything.

 

Exactly. And it's important.

What are you using? Expires? Expires sucks. How about ETags? ETags are more-or-less perfect, provided the backing information is chosen well (defaults are normally fine).

 

We're saying two different things. But I've tried to get us on the same wavelength and that isn't working, so I'm bowing out of this argument.

 

I stand by my "not using the right directives" comment. And see above replies.

 

A random number is more than you need. The time is sufficient.

<?php
    $time = time();
    $content1 = '<a href="http://example.net" title="Example 1" target="_blank"><img src="http://example.com/gallery/image-1.png?' . $time . '" alt="Image 1" width="300" height="250" class="gallery-image"></a>';
    $content2 = '<a href="http://example.net" title="Example 2" target="_blank"><img src="http://example.com/gallery/image-2.png?' . $time . '" alt="Image 2" width="300" height="250" class="gallery-image"></a>';
    $content3 = '<a href="http://example.net" title="Example 3" target="_blank"><img src="http://example.com/gallery/image-3.png?' . $time . '" alt="Image 3" width="300" height="250" class="gallery-image"></a>';
    $content4 = '<a href="http://example.net" title="Example 4" target="_blank"><img src="http://example.com/gallery/image-3.png?' . $time . '" alt="Image 4" width="300" height="250" class="gallery-image"></a>';
    $content = array($content1, $content2, $content3, $content4,);
    shuffle($content);
    ?>
    <?php print $content[0] ?>

 

Agreed. Expires sucks. Just starting muck around with Etags but I see some issues on the horizon where images are stored on a CDN (Amazon) vs. the local server. I'll check it more.

 

If you have a sample of a directive that works across the board I'll be fully thankful and appreciative, but all I've seen (and most of what I've read) indicates consistent inconsistency.

 

Your $time = time has promise. Indeed, it drops in a number string, but I'm still seeing browsers cache the same page so what I'm not sure of is how frequently PHP creates the number appended to the image URL.

 

I'll post a live sample site in a few minutes using the code above as well as an iFrame solution.

OK, here's a live sample:

 

Mac360.org

 

In the right sidebar are two images (from an array of 12).

 

The Top Right Sidebar Image uses iFrame but accesses the same images from the same array.

 

The Bottom Right Sidebar Image uses the PHP array from Requinix above, and, indeed appends the version/query string, but I've noticed that the time is not updated quickly. Not sure how that happens in that PHP array.

 

As for htaccess, I've used plenty of directives with much the same results. Works on some browsers, but not on others:

<IfModule mod_expires.c>    ExpiresActive off
</IfModule>


<IfModule mod_headers.c>
    Header unset Cache-Control
</IfModule>

That one among others, including this (htaccess in the image directory), work sporadically.

<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 2 seconds"
ExpiresByType image/png "access plus 2 seconds"
</IfModule>

Again, the objective is to have the images rotate and not be cached by the browser. In Safari both image change as desired. In Chrome, only the top image (iFrame) will refresh and change, while the bottom image remains the same.

Expires sucks. The problem is that it instructs the browsers to not even try to retrieve content until the time has passed. Don't use it. Remove all that stuff.

 

Use ETags instead. The server will send a hash with the content that (should) only change when the file changes. The client will keep trying to request the file, but will send the last hash it knew about. Then the server will reply with either (a) yes, the file has changed and here it is with the new hash, or (b) no, the file has not changed so use what you have cached.

It doesn't save as much bandwidth as Expires does (there's still the overhead for each request to check the hash) but it saves you the hassle of dealing with query strings and such.

 

<Files ~ "\.(css|gif|jpe?g|js|png)$">
	FileETag All
</Files>
You may need to unset other caching headers, mostly just Cache-Control, Expires, and Pragma, if they're being sent automatically.

Use ETags instead. The server will send a hash with the content that (should) only change when the file changes. The client will keep trying to request the file, but will send the last hash it knew about. Then the server will reply with either (a) yes, the file has changed and here it is with the new hash, or (b) no, the file has not changed so use what you have cached.

It doesn't save as much bandwidth as Expires does (there's still the overhead for each request to check the hash) but it saves you the hassle of dealing with query strings and such.

 

<Files ~ "\.(css|gif|jpe?g|js|png)$">
	FileETag All
</Files>
You may need to unset other caching headers, mostly just Cache-Control, Expires, and Pragma, if they're being sent automatically.

 

 

Thanks Requinix.

 

Alright. Looks good, but to be honest finding something on the interwebs that's related to step-by-step is a challenge, plus lots of folks with pros and cons, disputes over configuration, and even some overhead issues, et al (not that having PHP serve a tagged image isn't overhead). I'm sure they're around, but I haven't been able yet to find options that describe how to turn on ETags easily. Apache is a good source for the geekier minded than me, but I'm digging into it.

 

From what I can see of your directive above I should be able to drop it into the images directory and somewhere set the ETag so it expires after x-seconds, but only for that directive. Is that correct?

 

Do you have a recommended source for more detail? Or, some examples. I'm wading through Google now.

ETags is built-into Apache. I'm surprised your server isn't configured to send them already, but whatever you can turn them on with that FileETag directive.

As for more information... I really don't know. Wikipedia is generally pretty good (at least with technical information). If MDN or MSDN have articles on it then I'd recommend those.

 

From what I can see of your directive above I should be able to drop it into the images directory and somewhere set the ETag so it expires after x-seconds, but only for that directive. Is that correct?

This has nothing to do with time. Time does not factor into any part of it.

 

1. The client requests the file for the first time.

2. The server calculates an identifier for the file. Like combining a few pieces of information together and hashing it. Make sure that information will accurately reflect whether a file has changed or not.

3. Server sends the file and the identifier. Client caches the file and the identifier.

4. Client requests the file for the second time, but sends the identifier it had learned previously.

5. Server calculates the identifier again;

a) If the identifier doesn't match then the file has changed, the server replies with the file and the new identifier and the process starts over

b) If the identifier matches then the file has not changed, the server replies without the file and the client reuses what it had cached previously

 

Client always re-requests the file every time. Server always checks if the file has updated before replying. Client only receives the file if it has changed.

 

Otherwise yes, you should be able to drop that code into a .htaccess and have it work.

ETags is built-into Apache. I'm surprised your server isn't configured to send them already, but whatever you can turn them on with that FileETag directive.

As for more information... I really don't know. Wikipedia is generally pretty good (at least with technical information). If MDN or MSDN have articles on it then I'd recommend those.

 

Client always re-requests the file every time. Server always checks if the file has updated before replying. Client only receives the file if it has changed.

 

Otherwise yes, you should be able to drop that code into a .htaccess and have it work.

 

 

Got it. Been digging around but man is there plenty of conflicting information out there. The common refrain for ETags is "turn 'em off."

 

So, basically, if ETags have been set up on Apache then simply putting it into the directive would make it active on that specific directory. Since each image served has a unique version/query appended would that be sufficient for the browser to detect that the ETag is serving a new file? That's the whole point. To keep the browser from caching the image at any time.

 

You've been very helpful and patient. Much appreciated.

The only times I've seen people say to not use ETags are:

a) Conflict between it and other caching headers - solution is to fix the headers, or use only one set of them

b) Incorrectly configured backing information - solution is to fix the backing information

c) Situations where ETags are not the best solution, or don't behave in the way that the caching requires - solution is, obviously, to use what's better

 

With a quick search around I see a lot of people saying to use them, so... any specific arguments against that you'd want me to address?

The only times I've seen people say to not use ETags are:

a) Conflict between it and other caching headers - solution is to fix the headers, or use only one set of them

b) Incorrectly configured backing information - solution is to fix the backing information

c) Situations where ETags are not the best solution, or don't behave in the way that the caching requires - solution is, obviously, to use what's better

 

With a quick search around I see a lot of people saying to use them, so... any specific arguments against that you'd want me to address?

 

There seems to be plenty of conflicting information about using ETags. Some say use 'em, some say avoid 'em. I'm checking to see if my VPS server has it configured in Apache. Otherwise, sticking with iFrame works perfectly and has no caching problem whatsoever.

 

Thanks again for the help. It is appreciated. This is my first visit to PHP Freaks and the experience has been worthwhile.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.