3

I am currently storing svg code in arrays in a php file that, in short, I am then referencing to throughout the site to retrieve the desired image.

The file looks something like this:

<?php
$svg_ticons = array(...);
$svg_icons = array(...);
$svg_inputs = array(
    'checkbox_0' => '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0" y="0" viewBox="0 0 60 60" enable-background="new 0 0 60 60" xml:space="preserve"><symbol id="Checkbox_Blank" viewBox="-7.5 -7.5 15 15"><path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M-4.81 6.97h9.63c1.19 0 2.16-0.97 2.16-2.16v-9.63c0-1.19-0.97-2.16-2.16-2.16H-4.81c-1.19 0-2.16 0.97-2.16 2.16v9.63C-6.98 6-6 6.97-4.81 6.97L-4.81 6.97z"/><path fill="#333333" d="M4.82-7.5h-9.63c-1.48 0-2.68 1.21-2.68 2.69v9.63c0 1.48 1.2 2.69 2.68 2.69h9.63c1.48 0 2.68-1.21 2.68-2.69V-4.81C7.5-6.29 6.3-7.5 4.82-7.5zM-4.82 6.45c-0.9 0-1.64-0.73-1.64-1.64V-4.81c0-0.9 0.74-1.64 1.64-1.64h9.63c0.9 0 1.64 0.73 1.64 1.64v9.63c0 0.9-0.74 1.64-1.64 1.64H-4.82z"/></symbol><use xlink:href="#Checkbox_Blank" width="15" height="15" x="-7.5" y="-7.5" transform="matrix(4 0 0 -4 29.9997253 29.9989338)" overflow="visible"/></svg>'
);

$svgall = $svg_ticons+$svg_icons+$svg_inputs;
if(array_pop((explode("/", $_SERVER['SCRIPT_FILENAME']))) == array_pop((explode("/", __FILE__)))){
    if($reqsvg = $_GET["r"]?:false){header("Content-type: image/svg+xml"); echo $svgall[$reqsvg]; exit();}
}
?>

So the when I call to these images, let us say, as a background-image, it looks something like this:

background-image:url(DOMAIN/images/svg.php?r=checkbox_0);

Unfortunately, these 'images' are not being cached, which is causing a very undesirable delay time upon page load. So my question is: How can I cache from urls with query string? (.htaccess solution is prefered.)

Side Note: I am aware of this post. However, the answer marked is not my solution.

Edit: I am not simply asking how to enable caching. I am already aware of how to do that. Parts of my site are caching beautifully. I am looking to specifically cache from urls with a query string.

Community
  • 1
  • 1
Crystal Miller
  • 741
  • 10
  • 26
  • You will probably need to make sure the header is being sent and then maybe use ExpiresByType from mod_expire. http://httpd.apache.org/docs/current/mod/mod_expires.html – Panama Jack Jun 25 '15 at 20:49
  • [Setting cache-control headers in PHP.](http://stackoverflow.com/a/4485194/1064767) [A decent explanation of the Cache-Control values.](http://stackoverflow.com/a/4480318/1064767) – Sammitch Jun 25 '15 at 20:57
  • 1
    Have you tried this from a variety of browsers (or devices)? It's possible that the settings for the particular browser with which you are testing has some environment setting that's causing the resources to be aggressively re-downloaded. – Jerbot Jun 25 '15 at 21:44
  • @PanamaJack What would you suggest I set the ExpiresByType to? As far as I know there is not a file type for a Query String. – Crystal Miller Jun 25 '15 at 22:01
  • @Sammitch The first link you gave looks like it would work however I haven't been able to make it work. Though I really feel like it should, so I would like to keep working with it. The second link however, seemed a little far off from what I was looking for. – Crystal Miller Jun 25 '15 at 22:05
  • @SuperJer Given that this is the only file that I am having caching trouble with, I am fairly certain that that is not the issue. – Crystal Miller Jun 25 '15 at 22:07
  • 1
    An `.htaccess` solution may not work or may be more complicated, since it looks like you're serving the svg using php. If you put the following at the top of your svg.php file, what happens? `header('Expires: ' . gmdate('D, d M Y H:i:s', strtotime('+1 hours')) . ' GMT');` – Jerbot Jun 25 '15 at 22:13
  • That breaks the images. I believe there must be a syntax error, but I can not seem to find it. – Crystal Miller Jun 25 '15 at 22:47
  • It's quite possible. I threw that in there without the ability to test it. You can always save a broken image and load it in a text editor to see if there are any errors or warnings that php threw. – Jerbot Jun 26 '15 at 14:47

2 Answers2

1

What you want to do, if I understand correctly, is not possible without some awful hacks I can't even think of and would advise against anyway.

The way caching works is, I believe, in a key - value storage system, where the key is the URI + the query string. So the browser will save your image with a certain key, when there is an image requested with the same key the browser will use the cached version if it matches expiration criteria or will send a request to see if the file has been modified.

In your case it seems like the r=checkbox_0 part of the query string is dynamic, meaning it changes it's value every time you refresh the page. You cannot cache this for the reason I mentioned above. If you're getting a different query string each time, the browser will eventually end up caching a separate image every time.

IMO the best you can do is to use a static value for the r parameter, if that is possible.

Additionally, if you could cache images regardless of the query string then how would cache busting work :P

EDIT:

Here's the caching function, it takes in the time you want the cache to be active before expiring in seconds.

function cache($sec) {
    if ($sec > 0) {
        header('Cache-Control: must-revalidate, max-age=' . (int)$sec);
        header('Pragma: cache');
        header('Expires: ' . str_replace('+0000', 'GMT', gmdate('r', time() + $sec)));
    } else {
        header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
        header('Pragma: no-cache'); // HTTP 1.0.
        header('Expires: 0'); // Proxies.
    }
}
php_nub_qq
  • 15,199
  • 21
  • 74
  • 144
  • While query string are typically used for dynamicy, I am using so I can put all my SVGs in one file. All of these images have specific names, so no, they are not dynamic, but "r" can equal many different values. – Crystal Miller Jun 25 '15 at 22:45
  • @CrystalMiller if you try to access an image at the exact same URL twice it will be retrieved from the cache the second time. If not it means that there's a problem with your caching headers or something – php_nub_qq Jun 25 '15 at 22:47
  • One would think..... but everything else caches perfectly. It's just that this file has not been set up for caching, I suspect because it has no definitive filetype extension. – Crystal Miller Jun 25 '15 at 22:50
  • 1
    @CrystalMiller I can bet. You can cache whatever you want, if you have a URL like `http://example.com/news/page/*`, for some reason, then ultimately the file is `*` which is an invalid file name, however the browser will still cache it with proper headers – php_nub_qq Jun 25 '15 at 22:56
  • I believe that is actually what I wanted to know. However, I do not believe I did exactly what you were saying properly as it caused my entire site to go down. This is what I entered in my .htaccess file: "ExpiresByType /images/svg.phpr=*" Could you inform me of what I did incorrectly? – Crystal Miller Jun 25 '15 at 23:13
  • @CrystalMiller regulating the caching for this file from htaccess is going to be quite hard unless there is a way to specify caching information per file name as this is a php file no different from any of your other php files. Instead it would be easier if you set the caching headers in the file itself, before the output begins. I'll add a function of mine, I've gotten for quite some time now and has served me well for this purpose, in the question. – php_nub_qq Jun 25 '15 at 23:17
  • Headers in this file have done nothing for me. How would I get something like you meantioned, where it's http://example.com/news/page/*. Where would that go? – Crystal Miller Jun 25 '15 at 23:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/81585/discussion-between-crystal-miller-and-php-nub-qq). – Crystal Miller Jun 25 '15 at 23:33
  • @CrystalMiller sorry, I had to go away. That would be done exactly by headers from the file. In my MVC pattern I would call this function in the controller and the page would get cached. If it's not working for you it means something may be overwriting the values you set or is getting in the way. Inspect the request and see what are the values of the cache headers. – php_nub_qq Jun 26 '15 at 07:59
0

It was recommended that I put headers in my php file (php_nub_qq recommended a function & SuperJer recommended header('Expires: ' . gmdate('D, d M Y H:i:s', strtotime('+1 hours')) . ' GMT');).

I was fairly certain that putting headers in this file was doing nothing for me & SuperJer's code was breaking my images, though after messing with it the next morning with a fresh mind I finally figured out why.

This is the code I entered:

header("Expires: ".gmdate("%D, %d %M %Y %H:%i:%s", strtotime("+30 days"))."GMT");

However, I forgot in order to call strtotime in my site, I must first set date_default_timezone_set();

So the end result was:

date_default_timezone_set("America/Los_Angeles");
header("Expires: ".gmdate("%D, %d %M %Y %H:%i:%s", strtotime("+30 days"))."GMT");

However, upon further examination of Chrome's Network Developer Tool, I realized that SuperJer's initial suspicion of it being my browser setting was correct. My file had been caching all along, I'd just had "Disable Cache" checked in my developer tools. (Guess I was a bit more exhausted than I thought, because I could have sworn I checked that.)

Summary: If your query string is not dynamic & other things (such as images) cache on your site; close your eyes, take a nice long relaxing breath, & check all of your browser setting & do not forget your Dev Tool settings.

Community
  • 1
  • 1
Crystal Miller
  • 741
  • 10
  • 26