Forum Moderators: open

Message Too Old, No Replies

Having Trouble With Returned PHP Images

Having Image Cache Problems Maybe

         

socrtwo

6:22 pm on Apr 27, 2010 (gmt 0)

10+ Year Member



Hi. I got some good advice in another post to get me started. What I have at the moment is a blank map of the world. Users select countries for instance that they have visited, and this send an onclick request for a PHP file which with the GD image processing built into my ISP's php setup, colors the right country.

This set up works fine except once in awhile an image comes back bad and you just get an error. Sometimes this occurs because the PHP file name requested is wrong, but not always because sometimes if you uncheck the country and recheck it works correctly. Why is this?

Also I first process the PHP request through a javascript function so that if the checkbox started out checked, the click instead sends the request for the uncoloring version of the php file. Here is my javascript function from the inner frame where the checkboxes are:

function onBoxClicked(frame, country){
if (document.getElementById(country).checked == true){
window.parent.document.getElementById('world_map').src=(country)+".php";
document.getElementById(country).checked = true;
}else if (document.getElementById(country).checked == false){
window.parent.document.getElementById('world_map').src=(country)+"_unload.php";
document.getElementById(country).checked = false;
}
}

Some strange things have been happening though, like when I request an uncoloring, it might color two countries, or a coloring produces an image of the map representing a state of testing many clicks previous.

I think this means there is caching going on. So I looked up ways to stop caching. Obviously the best way is to change the name of the returned PHP image which replaces the previous occupant using the same javascript function and a src change. However how do I do this?

I can generate a random number with this javascriopt I know:

var randomNumber = Math.floor(Math.random()*100000001);

However, whenever I try to incorporate it into an image name, it doesn't work, I get an error back instead of my colored php image. I even tried to assign the image from a returned PHP image to a variable and then put the random number in front of that:

document.getElementById('world_map').src = country + ".php";
var loadImage = document.getElementById('world_map').src;
document.getElementById('world_map').src = randomNumber + loadImage;

My eventual goal is to have an image map that is clickable of the country so changes can be made directly to the image. I got this working for a few test large countries, but again, strange patterns of coloring and uncoloring occur. In other words, coloring one country might uncolor two etc. This seemed to be stopped in IE by making it always check for new versions of files within the browser preferences.

Here is the javascript function on the parent page that has the image map on it:

function onBoxClicked2(frame, country){
if (window.frames[frame].document.getElementById(country).checked == false){
document.getElementById('world_map').src = country+".php";
window.frames[frame].document.getElementById(country).checked = true;
}else if (window.frames[frame].document.getElementById(country).checked == true){
document.getElementById('world_map').src=country+"_unload.php";
window.frames[frame].document.getElementById(country).checked = false;
}
}

So here is my collection of code that I'm trying to use to stop caching. In the html I have these two lines for my parent and child files:

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="-1">

In all the php files there is this code:

session_cache_limiter('nocache');
$cache_limiter = session_cache_limiter();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");// Date in the past

Thanks for taking time to answer if you can!

daveVk

11:33 pm on Apr 27, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Your requests are
country + ".php"
and
country+"_unload.php"

so for example africa.php means ?

return last map anyone may have requested plus africa colored

If you only need one colored at a time, change requests to

country + ".php"
and
"noCountry.php"

If you need multiples colored request should be of form

map.php?c=africa,japan

socrtwo

12:50 am on Apr 28, 2010 (gmt 0)

10+ Year Member



Yes the map returned is the previously colored in countries plus the new country, for instance Egypt. Each user's world map is customized to include their IP at the beginning of the file name so it continues to build up with each onclick event.

I have an effort up and running already which waits for a submit button before coloring the countries. I'm trying to make this one a little more fun by coloring right away with each choice.

As for the errors, I was able to get rid of most of them by pausing the javascript for 500 milliseconds.

daveVk

2:54 am on Apr 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Each user's world map is customized to include their IP at the beginning of the file name


That is not evident here

document.getElementById('world_map').src = country+".php";

Does country include the IP address ?

A quick fix would be

document.getElementById('world_map').src = country+".php?t=" + timeStamp;

It is much safer to not guess the user and user state

- multiple users may be on same IP
- page may be in state of last cache
- user may have multiple copies of page open
- etc

socrtwo

4:54 am on Apr 28, 2010 (gmt 0)

10+ Year Member



OK, thanks for your reply. I need a way to keep building the same World map for the particular user. Each checkbox kicks off a small php file that adds the coloring of the specific country associated with the checkbox.

I guess this is primitive coding but I'm a hacker newbie. I'm not using AJAX here because I couldn't get it to work. My brother programmer told me I could use cookies to know which user and computer I'm dealing with, although cookies have a negative connotation for me.

I think using the time stamp might be a problem, I'm not sure. A user can click on the image map or the checkboxes faster than once a second, sometimes checking and unchecking the same box within the same second. Would that be a problem?

Also country+".php?t=" + timeStamp; is how the name of the PHP file is called, but doesn't the name of the file come back as just country+".php"? In other words, the png formatted newly further colored world map php file that is called as algeria.php?=04282010124732 return to be displayed simply as algeria.php with no date stamp anymore? If that is true, then doesn't the algeria.php file easily falls prey to some form of caching?

Thanks for your continued help.

daveVk

5:27 am on Apr 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Building a country list in javascript from all currently selected boxes, seems simpler and surer to me. Unless there are other reasons you don't need to know who the user is.

The js date function has sub second resolution, I think.

algeria.php?=04282010124732 would be cached as such, it is the full url, not the file name that is cached.

socrtwo

5:29 am on Apr 28, 2010 (gmt 0)

10+ Year Member



Heh very cool, I replaced your date function with my random number one. I looked the up the properties of the returned image and the
?r=" + randomNumber; 
part of the file is preserved. Thanks.

OK so the other problem is the return of errors. Maybe this occurs because the Javascript goes to the next line which makes sure the checkbox is checked (at least with the image map version of the function) before the PHP file has a chance to be returned.

To prevent this, do I just separate the functions and call both at the same time with the onclick event? Or is there a way to make the Javascript function pause until the image returns and loads? Or do you think there may be another reason why the little PHP files misfire and don't return images sometimes?

Below is a sample of the country PHP files for Guernsey an island off the British coast:

<?php
session_cache_limiter('nocache');
$cache_limiter = session_cache_limiter();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");// Date in the past
$ip=$_SERVER['REMOTE_ADDR'];
$oldImageName = 'world_map2_users_copy.png';
$newImageName = $ip.'.'.'world_map2_users_copy.png';
if (file_exists($newImageName)){
$im = imagecreatefrompng($newImageName);
}else{
copy($oldImageName, $newImageName);
$im = imagecreatefrompng($newImageName);
}
$guernsey_color = imagecolorallocate($im, 249, 221, 22);
imagefill($im, 631, 141, $guernsey_color);
ImagePNG($im, $newImageName);
ImagePNG($im);
ImageDestroy($im);
?>

daveVk

12:31 pm on Apr 28, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Take out all lines that set checked ? What are they for ?

Don't know why errors, does server log show anything, maybe backup of requests, perhaps threads fighting for use of same file.

You could put onload, onerror and onabort methods on the image, and serialize requests, messy.

socrtwo

7:36 pm on Apr 28, 2010 (gmt 0)

10+ Year Member



How do I serialize the request or, "queue" the php file calls?

The set checked lines may only be useful for the parent page version of the Javascript function, which is tied to the image map. It is a way to keep track of whether the country is colored or not so a second click will uncolor the country.

socrtwo

7:48 pm on Apr 28, 2010 (gmt 0)

10+ Year Member



Awesome, I put an onerror handler in the img tag which refreshes the image by filling it with the php script which is loaded when the page is first navigated to.

That makes for occasional image flickering. Is there an easy way to queue the php scripts?

socrtwo

9:34 pm on Apr 28, 2010 (gmt 0)

10+ Year Member



I read about php serialization and am thinking about using it. Is it kind of like zipping up php objects? Like in my post from 5:29 AM today, I could serialize the $im scalar? Then unserialize it and use it in another country file?

Using serialization, how could I retrieve an individual computer's (as opposed to an IP's) world map image file?

How would that prevent the errors?

By the way, I looked in the error log, it only shows up the stuff I can see in IE when there is a Javascript error. The image errors don't show up.

daveVk

2:03 am on Apr 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The server logs should show if there are problems on the server 404 vs 201 reply code, at least.

Is there a good reason why you don't implement it as just
map.php?c=japan,italy
without keeping maps for each user, and other complications ?

socrtwo

2:58 am on Apr 29, 2010 (gmt 0)

10+ Year Member



Dave, thanks for your continued interest. I'll look for more logs.

As for implementing map.php?c=japan,italy and the like, I'm guessing eventually the country string might get too long.

Another issue is that I also assume whereas each checkbox now calls only a small php file, loading and processing a big map file with all the country commands for each choice would be slower. I guess you could do a file include in the html file, but I tried that and it processed the whole php section immediately.

I want to preserve the semi-real term coloring because other similar services provide the same kind of updating.

BTW - what I'm aiming to be different about this new service are the countries are filled in with contrasting colors. Eventually I might want to give the user the choice about what color to use with each country but now I'm choosing colors sampled from the country flags depicted on Wikipedia and choosing the ones different from the choices I made for their neighbors.

daveVk

4:10 am on Apr 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There are about 250, two letter, ISO 3166 Country Codes, that should fit into 2K url with some spare room.

One php file with 250 ifs, should not be a problem, caching will know work, so for returning visitors at least it should be a lot quicker, if needed server caching could also be provided.

I want to preserve the semi-real term coloring because other similar services provide the same kind of updating.


No problem.

give the user the choice about what color to use with each country

I can not see many users bothering, it would require better identification of users.

socrtwo

4:55 am on Apr 29, 2010 (gmt 0)

10+ Year Member



OK I'll try changing it to your method, but to be the most efficient, isn't there a way to stack or make the php calls synchronous?

daveVk

7:25 am on Apr 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



a way to stack or make the php calls synchronous


Keep a busy indicator, requested by but not yet onload,onerror,onabort.

onclick, if busy set timeout to try later.

If not busy ask for all checked countries (timeout or onclick).