It's bugging me for a day now and I really cant find out, I have a basic login/register page, and when registering, a timestamp is stored in the mysql database(table timer, column cooldown):
$settime = mysql_query("INSERT INTO `timer` (`cooldown`) VALUES(0)") or die(mysql_error());
What I want to do now (I'm creating a browser mmorpg), Is when I do a specific POST request, I want a timer in my database to go off. This timer should be 1 minute, and also be shown for users, like: <?php echo $timer['cooldown']; ?> Whenever the timer is = 0, I can do a specific function again, and the timer will be set to 60 seconds again.
Sorry for the lack of knowledge but I can't find out anywhere how to do this.
What you're trying to do here - a background job - goes against the web development principle of a request-response cycle in the shared-nothing environment of PHP.
But there are several ways to break up the rigid cycle:
If you just need to do some DB updates after 1 minute, you can use MySQL events: http://dev.mysql.com/doc/refman/5.1/en/events.html
If the function you want to call is not running too long, you can check on every user request if there are entries in the timer table that are older than 1 minute.
Create a PHP script that is called by a cron job every minute. It checks if there are unhandled items in the timer table and does something with them.
Create a PHP daemon script that wakes up every minute to check.
If you need to change something on the user page after 1 minute, doing the PHP script call client-side with a JavaScript timeout and AJAX or websockets is the better option.
For displaying the countdown to the user, you have to use JavaScript. If you are using the server-side timer, you can use it just for display purposes, hiding the countdown when it's finished. To work around the "user opens new page before timout is finished" problem, put the data for the remaining seconds in an HTML data attribute where your JavaScript code can read it.
Related
Everything I google tells me this should not be happening, however it is.
I'm building a migration tool to build a 'master database'. I have an admin panel, only accessible to a few select people. There is a merge button that starts an AJAX call to run the migration php function. I'm not positive how long this script takes considering I'm still developing it but none the less I'm expecting a minimum of 20 minutes once pushed to production and populated with the production database. I do NOT need a lecture on best practices telling me not to do it via a GUI. This will become a cron as well, however I want to be able to induce it manually, if the admin desires.
So here's my process. The migration function immediately closes the session session_write_close() allowing me to run multiple php scripts simultaneously. I do this because I start a setInterval that checks to see a session variable. This is my 'progress' which is just an int on what loop iteration I'm on. In my migration script I open sessions, add 1 to that int, and close the sessions again. I do this at the end of each loop.
By doing this I have successfully created a progress for my AJAX. Now I noticed something. If I start my migration, then close out of my tab - or refresh. Once I reload the page my progress continues to grow. This tells me that the migration script is still executing in the background.
If I close 100% out of my browser, or clear my sessions I no longer see progress go up. This however is not because the script stops. This is because my progress indication relies on sessions and once I clear my sessions or close out my browser my session cookie changes. However I know the script is still running because I can query the database manually and see that entries are being added.
NOW to my question:
I do NOT want this. If my browser closes, if I press refresh, if I loose connection, etc I want the script to be TERMINATED. I want it to stop mid process.
I tried ignore_user_abort(false); however I'm pretty sure this is specific to command line and made no difference for me.
I want it to be terminated because I'm building a 'progress resume' function where we can choose where to resume the migration progress again.
Any suggestions?
UPDATE:
I didn't want to go this route but some solution I just though of is I could have another session variable. And it's my 'last time client was validated' which could be a timestamp. In my javascript, on the client side, every like 30 seconds I could hit a php script to 'update last time client was validated'. And in my migration function at the beginning of each loop I could check to make sure that timestamp isn't like 60 seconds old for example. If it IS 60 seconds old, or older, I do a die thus stopping my script. This would locally mean 'if there is no client updating this timestamp then we can assume the user closed out of his browser/tab/refreshed'. And as for the function I can ignore this check if in command line (cron). Not the ideal solution but it is my plan B
I am, and did, go with the solution to ping from the client to indicate if the client is still alive or not.
So essentially this is what I did:
From the client, in javascript, I set up a setInterval to run every 1.5 seconds and that hits a php script via AJAX. This php script updates a session variable with the current timestamp (this could easily be a database value if you needed to, however I didn't want the overhead of another query).
$_SESSION['migration_listsync_clientLastPing_'.$decodedJson['progressKey']] = time();
Then, inside my migration function I run a check to see if the 'timestamp' is over 10 seconds old, and if it is I die - thus killing the script.
if(isset($_SESSION['migration_listsync_clientLastPing_'.$progressKey])){
$calc = time() - $_SESSION['migration_listsync_clientLastPing_'.$progressKey];
if($calc > 10){
die();
}
}
I added a 'progressKey' param which is a random number from 1-100 that is generated when the function is called. This number is generated in javascript and passed into both of my AJAX calls. This way if the user refreshes the page and then immediately pressed the button again we won't have 2 instances of the function running. The 'old' instance will die after a few seconds and the new instance will take over.
This isn't an ideal solution however it is an effective one.
The "upon command" part of the title is essential. I know how to set a cron job to run a PHP file at a pre-determined time schedule. What I need is similar in nature, but I think it requires a different technical solution.
I have an admin section, and when one of my admins logs in, they should be able to click a button which gets a PHP script to execute every 5 minutes for the next 2 hours.
Right now the button exists, and it calls a Javascript function which sends an AJAX request to the appropriate PHP file. It would make our lives a lot easier if the PHP function in the file could be told to run every 5 minutes from that moment until 2 hours have passed.
I'm aware that something similar could be done client-side by having Javascript repeat the request every 5 minutes. However, that doesn't help me a lot. An admin needs to be able to leave the site, send new requests to the same file with different parameters, all the while not interrupting the repeated execution of the PHP script.
So, I need some sort of server-side solution for this. Is that even possible? If so, what do I do?
I can share the client-side code but I don't think it really matters - the client side is a standard AJAX call; on the server side it's just this:
$par=$_GET['par']; //parameter received from AJAX
someFunction($par); //I need to modify the code so this function (please note there's a parameter) would run every 5 minutes for the next 2 hours
A javascript solution would require that the admin would need to click the button then leave that page open for the next 2 hours which is far from ideal. I assume this is why you don't want this.
This is one method
When your admin clicks the button store the date and time in a database or file
Have a cron job run every 5 minutes regardless
The first thing the cron job does is check whether that stored datetime >= now - 2 hours
If it is not, 2 hours have passed since admin last pressed the button, die()
If another admin clicks the button just overwrite that datetime for that job with the new value. The job will then always run every 5 minutes for 2 hours since the last click.
Use the at shell command inside your php so it can call itself. Then use php to manage how many times its called or set them all up in one go
Any of the users can trigger an event, as many times they wish. Each time this event is triggered, a row in a mysql table is created with the timestamp, their userid and other useful information. What I need to do is launch a script which runs exactly 12 hours after the event is triggered i.e. for each row in the table.
How can I achieve this in an automated and efficient fashion?
You could use a cron job which every minute launches the script.
In the script you should first fetch the row(s) and check if it's OK to run (if 12 hours passed) then continue, else stop.
I don't know if this will be very efficient, it depends on your number of entries in the database, but technically it's not expensive to just check if the current date matches a date fetched from the database + 12 hrs, I cannot say more because you didn't give too much details about your data.
You'd probably be better off with a cronjob
http://en.wikipedia.org/wiki/Cron
Potentially, you could look into MySQL event scheduler. Although It might not fit your needs, hard to really tell on the details given
http://dev.mysql.com/doc/refman/5.1/en/events.html
something like
CREATE EVENT myTimedEvent ON SCHEDULE EVERY INTERVAL 5 minutes DO CALL updateRows();
updateRows checks your criteria (12hours ago), if it is, perform whatever action you want to do. This requires your MySQL to be # version 5.1+ however
You would probably best have a cron job which runs every minute and checks for any rows in the database > 12 hours old that have not yet been processed the script and process them. This wont give you EXACTLY a 12 hour difference, but would give you a difference within a minute of that.
You would probably also want to make sure that script would be able to run within a few seconds such that you don't have overlap of the script running twice at the same time.
This could be done using CronJobs. If you have root access to your Server or a server administration toolkit that offers cronjob managment you would do it on your server. otherwise use an online cronjob service (google for cronjob online).
the cronjob then triggers a php script on your server in your defined interval, like every minute or every 5 minutes.
this script then selects all rows from your mysql table which are older then 12 hours (WHERE timestamp <= NOW() - INTERVAL 12 hour ) and performs your desired actions on each result and delete the result from the table (or mark it done),
just make sure that the fetching and the actions itself are faster than your cronjob interval, otherwise you would have two or more scripts working on the same rows.
The easy way for me is to make the page head contains
<head>
<meta http-equiv="refresh" content="43200"> <!-- 43200 for (12 hours × 60 mintes × 60 seconds) -->
</head>
This method is very helpful to avoid server time out, which you can't avoid if you are using only PHP code
Important if you start the script using submit button, it's recommended to make the form action="other_page" not the same page, and sure you should save your input values as cookie using setcookie function and grab it as a variable in the action page using $cookieVar = $_COOKIE['the_cookie_name'] ;
You may need to increase or decrease the $cookieVar value and update the value again using setcookie every time your head code http-equiv do the refresh automatically after the specific seconds (43200 in our example) depends on what you want to do
Note that if you make your action start automatically without pressing submit button you can do the action in the same page.
I did that idea before, I had 180,000 images in one folder and the server didn't allow me to download it all because it was showing me only first 7998 images, so I create a script to zip each 1000 image in a file outside the images folder and to avoid time out, I made the code refresh each 60 second , finally I got only 180 zip file :)
basically i have a series of countdown timers for auctions on my site. i do this by storing the countdown end time in the database and use javascript to create the countdown. i was just wondering how i could have the web-server constantly check whether the countdown has finished and if is has, dynamically change the status of the auction from "not finished" to "finished". should i have a constantly running script on my web-server? that keeps querying the database to check if the countdown end-time has been reached?
p.s. im using apache, mySQL, and PHP
any views or help is appreciated!
Johnny
Constantly checking would not scale at all. It's unlikely the end time would change, so you can just deliver the end times of each auction to the web page and use javascript to change the status to finished when that time reached.
Sure, someone could edit the javascript and change the end times, but the client is only for display. You can do one final call to the server at the end time to check if the auction was extended. The server remains that authority. Any submission still needs to be check against the server time, not whatever was displayed on the user computer.
For me the logic goes like this
Load the default end time using database value and run counter through javascript.
when elapsed time is about to reach the auction end time say just 1 or 2 seconds before, you can check if the end time has changed and return the new value and feed it back to Javascript timer.
Above is applicable only if you increase end time for some reason.
If not than you can solely rely on javascript to count time for you and when end time is reached with javascript counter just make a quick ajax call to update your database (if it is required at all)
You should always load end time to your javascript function from your database
hello i have some problems with my php ajax script
i'm using PHP/mysql
i have a field in my accounts table that will save the time for the last request from a user, i will use that to kick the idle user out of the chat. and i will make a php function that will delete all the rows that its time field more than the time limit, but where should i use this method is it okay to fire it every time a new request sent to my index.php ? i think that will make a huge load on the server,is n't it ? do you have a better solution?
thanks
There are two viable solutions:
either create a small PHP script that makes this deletion in an infinite loop (and of course sleeps for a specified amount of time before doing it again), and then start it via PHP CLI,
or create one that makes the deletion only once, then exits, and call it from cron (if you're using a UNIXish server) or Task Scheduler (on Windows).
The second one is simpler, but its drawback is that you can't make the interval between the deletions shorter than 60 seconds.
A solution could be to fire the deletion function just once every few requests.
Using rand() you could give it a 1 in 100 (for example) change of running the function, so that about one page request in a 100 will clean up the expired data.