I have a PHP problem that is driving me a little crazy (probably because I'm no expert - I'm sure there is a solution!).
What I need to do is this:
1) Run a PHP script (readValues.php) which reads certain values from a MySQL database
2) Do something with those values to produce a result
3) Depending on the result, fire another PHP script (writeValues.php) which performs writes to the MySQL database every second. This script may run for many minutes so I want it running in the background
4) Send a response to the user from readValues.php as soon as the result is known. This is where my problem is - readValues.php is waiting for writeValues.php to complete before it sends a response to the web client
I have tried many suggestions from SO, including:
- include
- headers
- exit/return
- ob_flush
- exec with nohup
However no matter what I try, readValues.php always waits for writeValues.php to finish before it sends a response to the user.
Here is the guts of readValues.php:
<?php
include 'aorigin.php';
include 'conn.php';
$data = array("userID" => (int)htmlspecialchars($_POST["userID"]),
"userMaxTroops" => null,
"userCurrentTroops" => null,
"troopLosses" => 0,
);
function randBetween ($min, $max) {
// generates a random number between (and including) the minimum and maximum parameters
$num = 0;
$num = (mt_rand() / mt_getrandmax()) * ($max - $min) + $min;
return $num;
}
// get the user's current troops
$sql = "SELECT current_troops FROM Users WHERE user_ID ='" . $data["userID"] . "';";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
$data["userCurrentTroops"] = (int)$row["current_troops"];
$result -> close();
// determine troops lost
$data["troopLosses"] = round (randBetween (0, 5));
// send back the full data array - should only be used for testing and not in production!
echo json_encode ($data);
mysqli_close($conn);
// fire increment database script
if ($data["userCurrentTroops"] < $data["userMaxTroops"]) {
exec("nohup php incrementTroops.php " . $data['userID'] . " " . 5);
// return(exec("php incrementTroops.php " . $data['userID'] . " " . 5));
// exec("php incrementTroops.php " . $data['userID'] . " " . 5, $output);
// file_put_contents('file.txt', $output); // testing output of incrementTroops.php
// exit();
}
// include 'incrementTroops.php';
?>
And here is the guts of writeValues.php:
<?php
include 'aorigin.php';
include 'conn.php';
$increment = FALSE;
$troopsPerSquare = $argv[2];
$data = array("userID" => (int)$argv[1],
"userSquares" => null,
"userMaxTroops" => null,
"userCurrentTroops" => null,
);
do { //loop will run until we do not need to increment
$increment = TRUE;
// get the user's squares count
$sql = "SELECT COUNT(User_ID) AS numberOfSquares FROM Map WHERE User_ID = '" . $data["userID"] . "';";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
$data["userSquares"] = (int)$row["numberOfSquares"];
$result -> close();
// get the user's current troops
$sql = "SELECT current_troops FROM Users WHERE user_ID ='" . $data["userID"] . "';";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
$data["userCurrentTroops"] = (int)$row["current_troops"];
$result -> close();
// set the user's max troops
$data["userMaxTroops"] = $data["userSquares"] * $troopsPerSquare;
sleep(1); //wait for 1 sec before executing
$sql = "UPDATE Users SET current_troops = current_troops + 1 WHERE user_ID ='" . $data["userID"] . "';";
$result = mysqli_query($conn, $sql);
$data["userCurrentTroops"] += 1;
// set $increment as FALSE if we want get out of this loop
if($data["userCurrentTroops"] >= $data["userMaxTroops"]){
$increment = FALSE;
}
} while ($increment == TRUE);
mysqli_close($conn);
?>
Please note the above is very raw test code, so I have not written functions or added error checking etc. yet until I know I can solve this fundamental problem.
I would really appreciate any help!