[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1741
  • Last Modified:

onUnload PHP

Hi all:

I would like to update the value of an element in an array in PHP once a user leaves the page or closes the browser window. I know this would require JavaScript, so is there a way that PHP and JavaScript can talk to each other in this situation? Essentially, I am thinking I need to somehow tweak the "onUnload" attribute in the body tag.

Any help appreciated.

Thanks.

0
freezegravity
Asked:
freezegravity
  • 16
  • 14
  • 4
  • +2
2 Solutions
 
RoonaanCommented:
onunload='window.open('myphp.php','','width=100,height=100');'

-r-
0
 
askanthonysCommented:
or you could use ajax

searching google will return a bunch of results of stuff that would help you

or this to write a script element directly

var jsel = document.createElement('SCRIPT');
      jsel.type = 'text/javascript';
      jsel.src = 'http://www.website.com';
      document.body.appendChild (jsel);
0
 
RoonaanCommented:
Easier to do:

var v = new Image(1,1);v.src="http://www.mywebsites.com/myscript.php";

-r-
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
freezegravityAuthor Commented:
I very much appreciate the fast responses.

I think all of those redirect to the php page. What do I do on the php page? As in, I want to say  

if (browser_closed) {
  $myarray[1] = somevalue;
}

with all those comments, what would be the syntax for browser_closed?
0
 
freezegravityAuthor Commented:
Roonaan:

"onunload='window.open('myphp.php','','width=100,height=100');'"

I am not quite sure if this would work if the array is on the page calling it. i.e. the php is running on, in this example, myphp.php. I tried it, didn't work.

Could you elaborate?

Thanks.

0
 
siliconbritCommented:
FG,

The 'onunload' event is called when the browser window is closed (See: http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/events/onunload.asp).

Even though the browser window itself is closed, this does not stop the operating system calling some remote script on a server.  In your "myphp.php" script, you just need to write some code that stores the value you want to store.

If this value needs to be derived from the browser (e.g. the IP address of the client), you can choose what method you use to send that item of data to the script, there are lots of ways including:

   - make it a session variable.
   - use the POST or GET array.
   - ad nauseum :-D

I hope you get the picture.

Personally, I wouldn't bother with this technique anyway, the onunload event is a contentious issue in the world of security.  After all, when somebody closes a browser window, they want that to be the last thing that happens on that site.  I am a firm believer in things behaving as the user expects, so in all my experience, I have never used the onunload method.

Having said all that, you should look into Ajax as the preferred method for any callbacks on the server.  It's more reliable and intended for this sort of use.
0
 
Rob_JeffreyCommented:
I'm a little confused with the question.

You are trying to update an array on a PHP page - when the browser window that called the PHP page is closed?
PHP runs on the server.  Once a page is requested - any code on the page is executed - then passed to the browser.  So by the time the browser closes, the PHP code is long gone.  Any variables declared and used are destroyed and emptied.

If you want to store this information in a database - such as how many users are currently viewing the site - then you would want to save that information in a database.

What is it you are trying to do?
0
 
freezegravityAuthor Commented:
Sorry about the confusion:

Here is the bare bones, most simplistic description of my problem.

I have a single php page that works like this:
1) It has a maximum amount of users that can look at it at any given interval. Say 10 users max at any one time.
2) Each of the 10 users are represented in an array which contains their "expires_time". As in, after "expires_time" has been reached, that user is kicked off and another user takes his/her spot.

Problem: A user doesn't use all of their time. The resources are still locked up. In other words, if the timeout was 20 minutes, and a user just looked at it for a few seconds and closed the window, resources are still locked up for 20 minutes.

I want this page to set its expires_in time to zero (as in it expires now) when the user closes the window.

Hopefully this makes sense.

Thanks.
 
 
0
 
freezegravityAuthor Commented:
Oh and this page keeps track of the number of hits/array/etc. by using session variables. No databases, other php files, etc. involved.
0
 
Rob_JeffreyCommented:
How are kicking the users off?  Do you have the page refreshing in some way?
If you do - you can keep a counter going - $lastTimeUpdaed.  If $lastTimeUpdaed is greater than the standard refresh rate (plus a buffer %) - you can consider the user to have closed his/her window - and reclaim the resource.
0
 
freezegravityAuthor Commented:
well ... the user isn't "kicked off" as in the page goes bad or refreshes or anything. It is just assumed that in 20 minutes, the user has viewed the page and is not interacting with the server. If the user asks for some other request, then that user has to wait in line like every other person. So all that happens after 20 minutes is that a new expiring time is given to the new user at the same spot.

Here's the chain of events.

User 9 (key of 8 in the array) has 20 minutes
20 minutes over and the key of 8 in the array has a value of 0.
User u comes in and sees key 8 is empty.
User u (key of 8 in the array) has 20 minutes.

Thanks.
0
 
Rob_JeffreyCommented:
What is the resource?  Webcam or music or something?
There must be some form of interaction with the user for the server to know who is online before you can allocate a resource.
I can think of a few ways - but I don't know which to suggest.
0
 
freezegravityAuthor Commented:
well ... yes, the page contains a relatively big flash file. Before flash file is loaded however, it checks how many users already have access and if it is greater than some number then it redirects to another page saying "max users reached".
0
 
freezegravityAuthor Commented:
woops sorry ... it echos "max users reached" instead of <embed src=flashfile.swf>
0
 
Rob_JeffreyCommented:
You can place a LoadVars command within the flash file which posts to another php file on your server every so often.
This way you know exactly how many people are viewing the flash file.
0
 
freezegravityAuthor Commented:
problem is ... don't have access to the flash file itself. just know its location. I don't even have access to the swf, and definitely not the fla.

0
 
Rob_JeffreyCommented:
Too bad - that would have been the best solution.
Let me think...
0
 
Rob_JeffreyCommented:
How about frames?
You can launch the validated user in a framed window.  One frame is a single pixel wide which is set to update itself every x seconds - this points to a PHP file that takes care of the array.  The second frame points to the flash file.
Every time the page refreshes itself you know the user is still active.  You can even add java to know if the user surfs off somewhere else - if so close the frame.
0
 
freezegravityAuthor Commented:
Hmm ... Intriguing solution ... now I am thinking about logistics ... you would still need ...

1) the frames talking to one another to check each others status. How would this happen any other way except JavaScript, or get or post. Using get or post, wouldn't you have to redirect or whatever? If redirected, wouldn't the flash file start all over again?

2) What happens if the frameset itself is closed, resources are still blocked for 20 minutes for this one user which will be most of the time.

Answer these two and I'll think of other issues.

Thanks.

0
 
Rob_JeffreyCommented:
How are you currently storing the "who's online" array?  Database?
0
 
freezegravityAuthor Commented:
by a session variable. No databases involved.
0
 
freezegravityAuthor Commented:
more specifically, one session is given to all users that ever came in to my site. Not a single session per user. There is no such thing as "login" per se. Just One BIG session for all users ever.
0
 
Rob_JeffreyCommented:
So you have each client storing the entire array - or just their position in the array?
Ideally the server should be maintaining the resource - not the users.  If a use continues to view the flash file past the 20 minutes, how does the server know not to hand out another connection to a different user?
Could you use a database?  That would be my next suggestion.
0
 
siliconbritCommented:

FreezeG - have you asked yourself if you are doing the right thing here?

Bearing in mind that a flash object is downloaded to the client machine and executed there, why are you limiting access to it?  There is some underlying resource on the server that is accessed by each instance of the Flash object that you are actually trying to protect.

Describe what that resource is and perhaps Rob or I can give you some ideas on how to manage that resource effectively without having to limit access.

I have a client site that delivers an interactive flash object used all day by about 300 internal people.  Certain actions available in that object depend on a call-back to the web server.  In order to 'load-balance' the number of connections we distribute call-backs among several copies of the same script.  This is one rudimentary method of dealing with a specific problem.  I am sure your problem is sufficiently different that I would suggest a different approach, but I am sure there is more to it than access to a flash object.

What I am definitely sure about is that one single session used by multiple people is not the right approach.
0
 
siliconbritCommented:

..and just to underline a specific point.  Once a user has visited the site and seen the flash file, that file is stored in their internet cache.  They can look at it as many times as they like.

Is this flash file stored on some remote web site run by somebody you are not in contact with?

0
 
freezegravityAuthor Commented:
No ... the server is storing the array. The client gets a number based on the counter for all previous requests and that number is modulo'd to see if they are eligible for one of, in this example, 10 spots. Yes, a user could continue to "view" the flash file past twenty minutes (as in their connection is slower than 28k) and the server hands out another connection but that is an acceptable risk. I agree that a database would be a better solution. However, that still doesn't solve the problem of what happens when a file is closed.
0
 
Rob_JeffreyCommented:
If the information is stored on the server - then you can easily use frames, call backs, or any other method to time out the connections.
I agree with siliconbrit.  Perhaps you should review what it is you want to acomplish.
0
 
freezegravityAuthor Commented:
Sorry, had to comment out your questions to distinguish them and answer

//have you asked yourself if you are doing the right thing here?

Yes

//Bearing in mind that a flash object is downloaded to the client machine and executed there, why are you limiting access to it?

Because the network ppl here don't want like a 1000 simultaneous requests for the flash file. Thus the whole timeout, managing users things.

//Is this flash file stored on some remote web site run by somebody you are not in contact with?

Yes

//Describe what that resource is and perhaps Rob or I can give you some ideas on how to manage that resource effectively without having to limit access.

I am not protecting anything really. Just limiting the number of requests a day because I was asked to do this.

//What I am definitely sure about is that one single session used by multiple people is not the right approach.

Why not? Anyway, I think this is my only way with the limited amount of resources given to me.

Not that I mind alternate solution, I think that we have gone entirely too far beyond the specifications of my original question. Let's get back to talking between JavaScript and PHP.

Thanks.
0
 
freezegravityAuthor Commented:
//If the information is stored on the server - then you can easily use frames, call backs, or any other method to time out the connections.

How so?
0
 
Rob_JeffreyCommented:
Certainly.  
Is it possible for you to use a database to store the connection information?
0
 
freezegravityAuthor Commented:
//Is it possible for you to use a database to store the connection information?

Nope. The script is for another server and I do not know what database, if any, they may have.
0
 
Rob_JeffreyCommented:
Can you store the information in any way on the server?  Even flat files.
If you can store the data on the server (database or whatever) you can:


Each time a user requests the flash page - check to see how many rows are in the table.  
If there are more than 20 rows (max 20 users) then add the user's request into the table and do not allow them to the file.
If there are less, then let them see it.

If you use frames, then you can have the database 'time out' conenctions between that process above.
So;
User request page
Check for all users in the database that havn't responded in the last 5 minutes.
Delete those users (assume they are no longer connected)
Check to see how many are left
If less than 20 - let user see file - if not - add them to the que.

In the frames - you have one that is 1 pixel wide - invisible to the user - this frame refreshes itself every x seconds.
The refresh is requesting a php page which updates the database to say that user position x is still alive - so the next check will not delete this user.
The other frame shows the flash file.

Doing it this way you can also include a count down timer for the users waiting in the que.  Each time the 1 pixel frame refreshes - it is checking the approx time left for the next available slot.
0
 
freezegravityAuthor Commented:
//Can you store the information in any way on the server?  Even flat files.

haha ... NO ... I originally wanted a counter for my page that didn't require an external file because I don't have write privileges. Someone on experts-exchange figured out a counter using only sessions. it works quite brilliantly.

//Each time a user requests the flash page - check to see how many rows are in the table.  
If there are more than 20 rows (max 20 users) then add the user's request into the table and do not allow them to the file.
If there are less, then let them see it.

This is essentially what my program currently does. Substitute table for an array and you have my program.

//If you use frames, then you can have the database 'time out' conenctions between that process above.
So;


//User request page
 I assume you mean frameset page.

//Check for all users in the database that havn't responded in the last 5 minutes.
But they are just viewing the page, they won't really respond. You mean "response" to be anything sent to the client by the server?

/* Delete those users (assume they are no longer connected)
Check to see how many are left
If less than 20 - let user see file - if not - add them to the que.
*/
Sounds good. See above.

/*
In the frames - you have one that is 1 pixel wide - invisible to the user - this frame refreshes itself every x seconds.
The refresh is requesting a php page which updates the database to say that user position x is still alive - so the next check will not delete this user.
The other frame shows the flash file.

Doing it this way you can also include a count down timer for the users waiting in the que.  Each time the 1 pixel frame refreshes - it is checking the approx time left for the next available slot.
*/
I think this is the most valid solution ... I am still unsure about what happens if the entire frameset closes.

0
 
Rob_JeffreyCommented:
<If the entire frame set closes - then the client won't update the server - and will eventually time out in the database/array>

Without the server being in control of the data (how many people are connected) I really have no idea how this can be accompished.
The server is relying solely on the clients for information.  If a brand new client connects - there is no data for the server to act on.  Therefore, the server will think there is no one connected and grant access.

I believe the question that *must* be answered here is - How can we store this information on the server?
0
 
askanthonysCommented:
isnt there a limit users line in htaccess that you could use?
0
 
siliconbritCommented:

Well there is no 'limitusers', but you can specify MaxClients, but not in the .htaccess file, only in the Apache server configuration block, and sadly FG wants to limit this solution to Javascript and PHP.

Hey Ho.

0
 
Rob_JeffreyCommented:
freezegravity, I just reviewed the post which Roonaan gave you the open 'Large" session code.
Your array is an open session.  Sessions are normally set up to be unique to each user. So instead of session_id('mycountersession'); you would be using session_id('someUniqueId');
This UniqueId would normally be a reference to a database table which the rest of the user's information can be pulled from (whats in their shopping cart, name, etc.)  Since you are using a single session for every user you have no way of identifying them individually.

I was thinking of using a session key named for the array position and the value being the the ip address of the client then a delimiter and the last time they updated.  That is assuming that every user will be coming in from a unique IP address.  In my office we are all behind a single router/firewall so we would all be seen as a single user.  I'm not sure if that would work in your situation - I'm assuming not.

$_SESSION[$array_position] = $_SERVER[REMOTE_ADDR] . ':' . $time_last_connected;

Instead of accessing a database you can now run through your session array to see who should be 'timed out'.  Anyone who hasn't updated their page in the last 5 minutes can be considered to be disconnected and removed from the array.

So - how do we uniquely identify the users?
0
 
Rob_JeffreyCommented:
By the way - sessions are being stored on the server.  So you do have write permissions on the server's session save path at the very least - another thing you can look into is writting a file in your session save path to maintain connections and their time-outs.  The only concern would be if the web server deletes files on a regular basis - at those times you would loose all your data.  But if it isn't a great concern you can do it that way.

echo session_save_path();
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 16
  • 14
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now