4

So, on my arcade, howlingdoggames.com. I have a points system that gives you a point every time you visit a page with a game on. To reduce abuse of this, I would like to make some sort of delay, so its only awarded after 45 seconds. Here's what I've tried:

if ($_SESSION['lastgame'] != $gameid) {
    sleep(45);
    $points = $points + $game_points;
    $_SESSION['lastgame'] = $gameid;
}

But this just seems to halt my whole website for 45 seconds, because this is in index.php, along with a lot of other code for my site.

Is there anyway I can isolate that bit of code, so it only makes the statement

$points = $points + $game_points;

wait for 45 seconds?

jkoop
  • 113
  • 1
  • 7

7 Answers7

9

There is (mostly) no multithreading in PHP. You can sort of do this with forking processes on Unix systems but that's irrelevant because multithreading isn't really what you're after. You just want simple logic like this:

$now = time();
session_start();
$last = $_SESSION['lastvisit'];
if (!isset($last) || $now - $last > 45) {
    $points = $_SESSION['points'] ?? 0;
    $_SESSION['points'] = $points + 10;
    $_SESSION['lastvisit'] = $now;
}

Basically only give the points if the increment between the last time you gave points is greater than 45 seconds.

jkoop
  • 113
  • 1
  • 7
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 1
    Oddly random downvote on this. Just curious if there was a reason or it was a failed tactical downvoting attempt? – cletus Oct 24 '09 at 09:23
  • 1
    It wasn't me, but the code example doesn't actually answer the question, as this should happen only after you visit a new game + you have a typo in `$_SESSION['last']`. – Lukáš Lalinský Oct 24 '09 at 09:27
8

It is session block your script. not "There is no multithreading in PHP". session_write_close() before sleep() will solve block your whole script. but may not fit in your problem.

so you had to save the bonus using settimeout of js and AJAX.

from comment of sleep() in php.net: http://www.php.net/manual/en/function.sleep.php#96592

Notice that sleep() delays execution for the current session, not just the script. Consider the following sample, where two computers invoke the same script from a browser, which doesn't do anything but sleep.

bronze man
  • 1,470
  • 2
  • 15
  • 28
2

No, not directly. You need to take a different approach, like remembering the timestamp of last visit and only add points if sufficient amount of time has passed since that.

Anti Veeranna
  • 11,485
  • 4
  • 42
  • 63
2

There is no multithreading in PHP, so sleep() is always going to block your whole script.

The way you should solve this is to record the the time of the last game, and only award points if it is more than 45 seconds later than that.

<?php
session_start();
if (!isset($_SESSION['last_game_time'])
    || (time() - $_SESSION['last_game_time']) > 45) {

    // code to award points here

    $_SESSION['last_game_time'] = time();
}

Bear in mind that users could still abuse this if they disable cookies (thus they will have no session data). So if that really worries you, check that they have cookies enabled before allowing them to use the feature (there are probably several questions that cover this).

Ben James
  • 121,135
  • 26
  • 193
  • 155
1

Instead of blocking the script, save the current time in the session, don't add the points and let the page render. Then on later page views if you see that the saved time in session is older than 45 seconds, add the points, store them wherever you need, and clear the time.

Lukáš Lalinský
  • 40,587
  • 6
  • 104
  • 126
0

You cannot, but you can make this code a javascript one, and save the bonus using AJAX.

Bite code
  • 578,959
  • 113
  • 301
  • 329
0

Problem is session_start();

Try

if ($_SESSION['lastgame'] != $gameid) {
    session_write_close();
    sleep(45);
    session_start();
    $points = $points + $game_points;
    $_SESSION['lastgame'] = $gameid;
}
James Risner
  • 5,451
  • 11
  • 25
  • 47