I can't understand how and why my mysql_query command stops it's execution.
There are two arrays I work with:
routersTree (includes about 100 rows)
dates (includes about 30 cells)
Here the code:
while ($i <= count($routerTree)){
$currentRouter = $routerTree["router_$i"];
echo "<td>$i</td>";
for ($j = 0; $j < count($dates); $j++) {
$sql = "SELECT indications.id_device FROM indications LEFT JOIN routers ON indications.id_device = routers.id_device WHERE routers.id_router = $currentRouter[id_router] AND date(indications.dateField) = '$dates[$j]' ORDER BY routers.id_device";
if ($res = mysql_num_rows(mysql_query($sql))) {
echo "<td>$res</td>";
}
else {
echo "<td>error</td>";
}
}
}
It stops my cycle after 18-th row, but there are about 82 cycles more to do.
My guess is, that there is a small timeout for mysql_query command.
Any help would be appreciate.
Well, after continue finding the solution of my problem I finaly found one. So easy and so fast... The problem was in PHP timeout. I just added into my settings.php file next entry:
ini_set ('max_execution_time', 0);
The default value is 30 seconds. 0 means the infinite loop. But be careful with this thing. Rise the value for your needs, but try not to use infinite loop.
Related
I have an end point that I can send a GET request to and it returns a different result depending on the limit and offset.
https://example-foo-bar.com?l=100&o=0 // returns the first 100 items.
I want to create a for loop (or a Nested for loop I assume) that returns a 100 items at a time, adding the result to an array each time, until the end of the response. I have the code for sending the curl request and storing the result, just struggling on the batch processing part.
Something like:
https://example-foo-bar.com?l=100&o=0
https://example-foo-bar.com?l=100&o=99
https://example-foo-bar.com?l=100&o=199
https://example-foo-bar.com?l=100&o=218 // end of response ?
I also know how many result there are in total, stored as $count;
I ended up with something like this but it doesn't feel like the best practice:
function testLoop(){
$limit = 100;
$count = getCount();
$j = ceil($count/$limit);
for ($i = 0; $i < $j; $i++){
$offset = $i*100;
echo 'https://example-foo-bar?l='.$limit.'&o='.$offset.'';
}
}
testLoop();
I am not sure if I understand the question correctly. But are you looking for something like that?
$offset = 0;
$limit = 100;
$run = true;
$result_array = array();
while($run) {
$result_array = array_merge($result_array, json_decode(file_get_contents("https://example-foo-bar.com?l=".$limit."&o=".$offset),true));
$offset = $offset + $limit;
if($offset == {somenumber}) {
$run = false;
}
}
Then use a cron job to call the php file
Create table 'schedule' and store the data id, link_name,offset and status column
set cron to execute every 10 minutes and take First an entry (one) which status =0
pass param to testLoop($limit) to call function. It may entire link of only offset =0, offset =99, offset =199 like that
After completed to update status=1 in schedule table.
After 10 minute cron Call Step1.
Best way to use Cron for such type of batch process you can also use php-resque
I have a conundrum I'm struggling to crack.
I have a database with 719 entries that I'm running a script on, these entries are Characters in a game and is what they will be referenced as.
However my while loop stops at 360 every time...
See below:
$query = mysqli_query($con,"SELECT * FROM users ORDER BY entryID;");
// Start loopy loop
$runCount = 0;
$CharNum = 0;
echo "NumRows = ".mysqli_num_rows($query)."<br/>"; // Outputs: NumRows = 719
while ($row = mysqli_fetch_array($query)) {
echo "Character#: ".++$CharNum."<br/>"; // Outputs: Counter stops at 360??
$entryID = $row["entryID"];
$CharacterID = $row["characterID"];
$blue = $row["blue"];
$tsDatabaseID = $row["tsDatabaseID"];
$tsUniqueID = $row["tsUniqueID"];
$tsName = $row["tsName"];
if (...[tonnes of code here]
}
echo "Runcount = ".++$runCount."<br/>"; // Outputs: Another counter stops at 360??
}
echo [some report summary]
I have no idea how or why it is stopping, but it isn't crashing as the report summary is showing after the while finishes but it is too perfect to be 360 every time??
So fun story,
if (!mysqli_fetch_array($query)) {
Doesn't sanity check it like I thought to see if it's valid, but performs the fetch in a way it screws everything up. Perhaps someone can explain this who is better than I. But this was inside my if.
I created a function inside a longer plug-in for shopware, which is supposed to create a random number for every row in the database that has a "NULL" value in the "vouchercode" column. Right now I replaced the for-loop condition with a fixed number, because I wanted to make sure the problem doesn't occur because of the for-loop condition.
The problem is, that the for-loop just has effect on the database once.
For instance: I have this table 's_plugin_tnev'. Inside of that table are 6 rows. 4 of these have "NULL" as value inside of the vouchercode column.
So as far as I understand my code. It should loop 5 times through the same table and every time update one of those "NULL"-value columns, meanwhile after every loop one of those "NULL"-value columns should be filled with a random number and therefore no longer be SELECTed nor UPDATEd by this for-loop.
Though as mentioned earlier this doesn't happen. The for loop just works once apparently.
Here is my code snippet:
public function generateCode()
{
//Repeat action 5 times
for($i = 0; $i <= 4; $i++)
{
$rand = 0;
//Creates 16 times a number and add it to the var
for ($i = 0; $i<15; $i++)
{
$rand .= mt_rand(0,9);
}
//On Checkoutcomplete add $rand to database table
$addInt = "UPDATE s_plugin_tnev SET vouchercode = $rand
WHERE vouchercode IS NULL
LIMIT 1";
$connect = Shopware()->Db()->query($addInt);
}
}
As you can see I use the DBAL Framework, because this is the best supported way by Shopware.
My idea would be that the mistake has something to do with the $connect variable or that DBAL is not communicating fast enough with the Database.
Maybe someone has more experience with DBAL and could help me out.
Thanks in advance,
Max K
You have two for loops with $i, so on your first iteration, at the end the $i value is 15 and the first loop is executed only once.
Try this instead :
public function generateCode()
{
//Repeat action 5 times
for($i = 0; $i <= 4; $i++)
{
$rand = 0;
//Creates 16 times a number and add it to the var
for ($j = 0; $j<15; $j++) // $j NOT $i <---
{
$rand .= mt_rand(0,9);
}
//On Checkoutcomplete add $rand to database table
$addInt = "UPDATE s_plugin_tnev SET vouchercode = $rand
WHERE vouchercode IS NULL
LIMIT 1";
$connect = Shopware()->Db()->query($addInt);
}
}
I have a question that I have been stuck on for several hours now. I have played around with numerous types of for() and while() loops. I put them in different locations with different variables and ran different things, nothing worked..
My question:
Why is my program giving all users below the first one the same level? You can clearly see in the picture that Nicolas has much more XP. (5,000 xp is level 20, and if "Nic5" was first in the database then it would change the "Skill Level" to 20.
I know that the returned variable $lvl isn't changing for each player that loads and this is why each player is getting the first player's level.
Can anybody help me with this please?
Notes:
0 = a column that holds experience for a players skill level.
class calculatelevel:
class calculatelevel {
function level($skillnum)
{
$host = "*";
$user = "*";
$pass = "*";
$db = "*";
$con = new mysqli($host, $user, $pass, $db) or die($con->error);
$res = $con->query("SELECT `0` FROM hiscores");
$max = 99;
while($row = $res->fetch_assoc()) {
$xp = $row['0'];
// Find the appropriate level
for ($lvl = 1; $lvl < $max; $lvl++) //this for loop runs 99 times
{
if ($xp < $this->experience($lvl))//if players xp in skill is less than experience(level 1-99)
{
// Level found
$lvl -= 1;
break;
}
}
}
return $lvl;
}
public function experience($lvl)
{
$xp = 0;
for($x = 1; $x < $lvl; $x++)
{
$xp += floor($x + 300 * pow(2, ($x / 7)));
}
return floor($xp / 4);
}
}
Method that writes database information to page.
if($res->num_rows > 0) {
echo "<table>
<tr>
<td>Rank</td>
<td>Username</td>
<td>Skill Level</td>
<td>Total Exp</td> </tr>";
while($row = $res->fetch_assoc()) {
echo 'ran';
$calc = new calculatelevel();
$level = $calc->level(0);
echo '<tr>
<td>'.($count+1).'</td>
<td>'. htmlspecialchars($row['username']) .'</td>
<td>'.number_format($level).'</td>
<td>'.number_format($row['0']).'</td>
</tr>';
$count++;
}
}
Your while loop and for loop are structured incorrectly. You are looking at only the first row and returning the level for that row every time. You break the for loop when you find the level for that row's player, then immediately return that level. Result: it looks like everyone has the same level.
EDIT: Okay, here are a few more thoughts.
First, a column named 0 is asking for trouble, as Mike W pointed out. You say 0 is a table, but if that's the case, your SELECT statement doesn't make sense. The first thing I would try is changing the column name to something that isn't a number, like xp.
Second, you really should make only one database connection and use it throughout the entire request, if possible. Opening a new connection each time a particular function runs will tie up a server quickly.
Third, the obvious problem in your current code is this:
function level($skillnum) {
// other code here....
// Okay, you load a row's data into $row, with the idea that you will repeat this.
while($row = $res->fetch_assoc()) {
// $xp is set to the experience points for the user you just loaded
$xp = $row['0'];
// You now look at each level, starting at 1, to see if the
// user's xp is greater than the cutoff for that level
for ($lvl = 1; $lvl < $max; $lvl++) //this for loop runs 99 times
{
// If the user's xp is less than the cutoff...
if ($xp < $this->experience($lvl))//if players xp in skill is less than experience(level 1-99)
{
// ... then you go back down one level...
// Level found
$lvl -= 1;
// ... and quit the for loop!
break;
}
}
// okay, you're out of the for loop, so you go back to the while loop...
// a new row is loaded...
// and $xp and $lvl are both overwritten with that user's values
}
// So, the while loop has run once for each player...
// ... but you are only returning one player's level!
return $lvl;
}
Also, you have defined calculatelevel::level to require a parameter $skillnum, but you never use it in the code posted here.
I suspect there is another glitch in your real code causing it to return the first player's level, rather than the last player's level. It could be a problem with the 0 column name; that really should change.
I checked throught the existing topics. I have a fix for my problem but I know its not the right fix and I'm more interested making this work right, than creating a workaround it.
I have a project where I have 3 tables, diagnosis, visits, and treatments. People come in for a visit, they get a treatment, and the treatment is for a diagnosis.
For displaying this information on the page, I want to show the patient's diagnosis, then show the time they came in for a visit, that visit info can then be clicked on to show treatment info.
To do this a made this function in php:
<?
function returnTandV($dxid){
include("db.info.php");
$query = sprintf("SELECT treatments.*,visits.* FROM treatments LEFT JOIN visits ON
treatments.tid = visits.tid WHERE treatments.dxid = '%s' ORDER BY visits.dos DESC",
mysql_real_escape_string($dxid));
$result = mysql_query($query) or die("Failed because: ".mysql_error());
$num = mysql_num_rows($result);
for($i = 0; $i <= $num; ++$i) {
$v[$i] = mysql_fetch_array($result MYSQL_ASSOC);
++$i;
}
return $v;
}
?>
The function works and will display what I want which is all of the rows from both treatments and visits as 1 large assoc. array the problem is it always returns 1 less row than is actually in the database and I'm not sure why. There are 3 rows total, but msql_num_rows() will only show it as 2. My work around has been to just add 1 ($num = mysql_num_rows($result)+1;) but I would rather just have it be correct.
This section looks suspicious to me:
for($i = 0; $i <= $num; ++$i) {
$v[$i] = mysql_fetch_array($result MYSQL_ASSOC);
++$i;
}
You're incrementing i twice
You're going to $i <= $num when you most likely want $i < $num
This combination may be why you're getting unexpected results. Basically, you have three rows, but you're only asking for rows 0 and 2 (skipping row 1).
Programmers always count from 0. So, you are starting your loop at 0. If you end at 2, you have reached 3 rows.
Row0, Row1, Row2.
if $i = 0, and u increment it BEFORE adding something to the array, u skip the first row. increment $i AFTER the loop runs to start at 0 (first key).
For loops are not good for this: rather do:
$query=mysql_query(' --mysql --- ');
while ($row=mysql_fetch_array($query)){
$v[]=$row["dbcolumn"];
}
return $v for your function then.compact and neat. you can create an associative array, as long as the key name is unique (like primary ids).. $v["$priid"]=$row[1];