for loop, $i equals two different values in the same loop - php

I have a small form that is generated from a mysqli->query and I've set each inputs name to be an array, such as name="Shift_ID[]". Then I have a for loop that is meant to UPDATE the records one at a time as it loops through. The problem I have is that the $i variable is a different value within the same loop and I don't understand why. This is my code:
if(isset($_POST['update_submit']))
{
$id = $_POST['Shift_ID'];
$name = $_POST['Shift_Name'];
$short_name = $_POST['Shift_Short_Name'];
$color = $_POST['Shift_Color'];
$shift_total_records = "5";
for($i = 0; $i <= $shift_total_records; $i++)
{
$sql = ("UPDATE shift SET Shift_ID = '$id[$i]', Shift_Name = '$name[$i]', Shift_Short_Name = '$short_name[$i]', Shift_Color = '$color[$i]' WHERE Shift_ID = '$i'");
echo "SQL: " . $sql . "<br>";
if(!$result_shift_update = $mysqli->query($sql))
{
die ('There was an error updating the shift table [' . $mysqli->error . ']');
}
}
}
The echo returns this:
SQL: UPDATE shift SET Shift_ID = '1', Shift_Name = 'Morning', Shift_Short_Name = 'AM', Shift_Color = '#FF0000' WHERE Shift_ID = '0'
I was expecting Shift_ID = '1' and WHERE Shift_ID = '1'. Can someone explain why this is happening? Also, before someone says it, I do know this is open to injection attacks and I need to use prepared statements.
*EDIT: * The reason I had it Shift_ID = '$id[$i]' and WHERE Shift_ID = '$i' was because I wanted to user to be able to change the Shift_ID field if they wanted to. The point would be to have the option to rearrange the order. The Shift_ID is the PRIMARY KEY, so they would get an error if they tried to use the same number twice, but is there a way to make this do what I want?

The first '1' is $id[$i] not $i - there is no problem evident here.

for($i = 0; $i <= $shift_total_records; $i++)
sets $i to 0, when you echo $id[$i] you will get the content in $id[0], the first id, but when you only echo $i you print 0 because you made $id = 0.

You've used a different variable in each location. Do you mean this:
$sql = ("UPDATE shift SET Shift_ID = '$id[$i]', Shift_Name = '$name[$i]', Shift_Short_Name = '$short_name[$i]', Shift_Color = '$color[$i]' WHERE Shift_ID = '$id[$i]'");

The first time you use $i you use it as follows $id[$i] the second time you just use $i....

Related

how to update column without using auto_increment value with 001 to so on

This is my table with name and unique numberenter image description here
This is my PHP code
$id = explode(",", $params["txtID"]);
for ($i = 0; $i <count($id); $i++) {
$sql = "SELECT 'auto_increment' as LastID FROM
INFORMATION_SCHEMA.TABLES WHERE table_name = 'esi_master' ";
$result = $this->con->query($sql);
if (intval($result->rowCount($result)) > 0) {
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
$lclId = intval($row["LastID"]) - 1 + intval('1');
$lclDcno = '00'.$lclId ;
echo $row["LastID"];
}
} else {
$lclId = intval($row["LastID"]) + intval('1');
$lclDcno = '00'.$lclId ;
echo $row["LastID"];
}
$sql = $this->con->prepare("UPDATE esi_master SET esi_status = 1,
esi_dcno = '$lclDcno[$i]' Where esi_id = '$id[$i]'");
echo $result = $sql->execute();
}
Here First I insert Names to the table using Insert Statements and next for some operation I update the Unique number unique number should start updating from the empty row, update done with unique id, The txtID contains ID`s like 1, 2, 3, 4 so on as I select table row in front end, in that basis that updates.Thanks in Advance.
You need another field to save, with type varchar(10).
data will not be able to save into integer(auto_increment)

How to run a sql query inside a while of another sql query?

Hi my code as follow:-
$sql="SELECT student_id,DA1,DA2,DA3,DA4,DA5,DA6,HA1,HA2,HA3,HA4,HA5,HA6 from table";
$results = $result->query($sql);
while($row = $results->fetch_assoc())
{
$id = $row['student_id'];
$marks1 = $row['DA1'] + $row['HA1']/2 ;
$marks2 = $row['DA2'] + $row['HA2']/2 ;
$marks3 = $row['DA3'] + $row['HA3']/2 ;
$marks4 = $row['DA4'] + $row['HA4']/2 ;
$marks5 = $row['DA5'] + $row['HA5']/2 ;
$marks6 = $row['DA6'] + $row['HA6']/2 ;
$i = 1;
while($i <= 6)
{
$sql = "SELECT `grade`,`point` FROM `grades` where ${'marks' . $i} BETWEEN min and max";
$results = $result->query($sql);
$row = $results->fetch_assoc();
${'grade' . $i} = $row['grade'];
${'point' . $i} = $row['point'];
$i++;
}
$totalcredit = 20;
$sgpa= ($point1*$c1 + $point2*$c2 + $point3*$c3 + $point4*$c4 + $point5*$c5 + $point6*$c6) / $totalcredit ;
$sql = "UPDATE table SET `G1` = '$grade1', `G2` = '$grade2' ,`G3` ='$grade3',`G4` = '$grade4',`G5` = '$grade5',`G6` = '$grade6', `SGPA` = '$sgpa' WHERE student_id = '$id'";
$result->query($sql);
}
In this code i am trying to calculate grade and sgpa of a class. In the first query selecting all the details and calulating total marks in six subjects. In the second query i am storing the grade and point in variables with respect to the marks and then calculating the sgpa. Then the update query is performed to store the details in database.
The table consist of 100 rows. The code is working for the first row but does not work for another rows and returns empty values. I am recursively trying to calculate and update the table with data of all students. I would be highly grateful if anybody can help in running the code for all the rows.
Change the inner while loop like this:-
$i = 1;
while($i <= 6)
{
$sql = "SELECT `grade`,`point` FROM `grades` where ${'marks' . $i} BETWEEN min and max";
$results2 = $result->query($sql);
$row = $results2->fetch_assoc();
${'grade' . $i} = $row['grade'];
${'point' . $i} = $row['point'];
$i++;
}
In your code $results is getting overrided so changing it to $results2 in inner loop will solve your problem.

How to deal with SELECT(MAX()) in mysql inside a foreach using PHP and Codeigniter

I'm using SELECT(MAX()) inside a foreach loop and this is my code:
foreach($_POST['image_Basename'] as $key=>$image_Basename){
$image_Title = $this->input->post('image_Title');
$image_Category_Id = $this->input->post('image_Category_Id');
$this->db->query("INSERT INTO mg_gallery (image_Group_Id, image_title, image_Basename, image_Category_Id)
SELECT 1 + coalesce((SELECT max(image_Group_Id) FROM mg_gallery), 0), '$image_Title', '$image_Basename', '$image_Category_Id'
");
}
The problem is that for each image_Basename, query produces a new number.
For example, if I got 3 image_Basenames, it will insert 1, 2 and 3 for those three image_Basenames. But I want it to insert the same number to all of image_Basenames.
For example, if the max number in the image_Group_Id is 1, then add number 2 for each image_Basename. How can I do that?! I've put
SELECT 1 + coalesce((SELECT max(image_Group_Id) FROM mg_gallery
outside of the foreach loop, but it didn't work!!!
The answer is added below by myself
EDITED 2
Try this if it works or not,
$maxRs = $this->db->query('SELECT max(image_Group_Id) AS max FROM mg_gallery');
echo $this->db->last_query();die; #run this query in your phpmyadmin and debug it.
if($maxRs->num_rows() > 0){
$maxData = $maxRs->row_array();
echo "here :".$maxID = $maxData['max'];die;
}else{
$maxID = 0;
}
//echo "max : ".$maxID;die; #check if its returning the corrent maxid or not.
foreach($_POST['image_Basename'] as $key=>$image_Basename){
$image_Title = $this->input->post('image_Title');
$image_Category_Id = $this->input->post('image_Category_Id');
$this->db->query("INSERT INTO mg_gallery (image_Group_Id, image_title, image_Basename, image_Category_Id)
$maxID, '$image_Title', '$image_Basename', '$image_Category_Id'
");
echo $this->db->last_query();die; #check the query its generating is correct or not and run directly at phpmyadmin
}
I'm not fully sure what kind of data you have and exactly what you want, but I'll help you towards the right direction:
$int_basename = (int)max($this->input->post('image_Basename'));
$str_image_title = $this->input->post('image_Title');
$str_image_category_id = $this->input->post('image_Category_Id');
$query = $this->db->query("SELECT max(image_Group_Id) AS max FROM mg_gallery");
$int_max = (int)$query->row()->max;
$arr_union = array();
for($i = 1; $i <= 3; $i++)
if ($i == 1)
$arr_union = "SELECT " . ($int_max + $i) . " AS id";
else $arr_union = "SELECT " . ($int_max + $i);
$str_union = implode(' UNION ', $arr_union);
$this->db->query("
INSERT INTO mg_gallery (image_Group_Id, image_title, image_Basename, image_Category_Id)
SELECT h.id, ?, ?, ?
FROM ({$str_union}) AS h
", array($str_image_title, $int_basename, $str_image_category_id));
This would only run the query twice and spare your database the trouble of loop queries. I also escaped the values through $this->db->query() as intended to avoid mysql injections. This doesn't really require INSERT ... SELECT as INSERT ... VALUES is enough.
First of all, you should never be inserting values directly from the POST array. But in the interest of just addressing the question at hand, I'll leave the code as is.
You need to query for the MAX(image_Group_Id) before starting the loop and not do a + 1 inside the loop. Like this:
$get_group_id = $this->db->query("SELECT 1 + coalesce((SELECT max(image_Group_Id) AS group_id FROM mg_gallery), 0)");
$get_group_id_array = $get_group_id->fetch_assoc();
$group_id = $get_group_id_array['group_id'];
foreach($_POST['image_Basename'] as $key=>$image_Basename){
$image_Title = $this->input->post('image_Title');
$image_Category_Id = $this->input->post('image_Category_Id');
$this->db->query("INSERT INTO mg_gallery (image_Group_Id, image_title, image_Basename, image_Category_Id)
$group_id, '$image_Title', '$image_Basename', '$image_Category_Id'
");
}
IT WORKS:
Specially thanks to Niloy Saha, finally, I got the answer, and this is the code I've used:
$getMaxValue = $this->db->query('SELECT 1 + coalesce((SELECT MAX(image_Group_Id)), 0) AS image_Group_Id FROM mg_gallery');
if($getMaxValue->num_rows() > 0){
$group_Id = $getMaxValue->row_array();
$image_Group_Id = $group_Id['image_Group_Id'];
}else{
$image_Group_Id = 0;
}
foreach($_POST['image_Basename'] as $key=>$image_Basename){
$image_Title = $this->input->post('image_Title');
$image_Category_Id = $this->input->post('image_Category_Id');
$this->db->query("INSERT INTO mg_gallery (image_title, image_Basename, image_Category_Id, image_Group_Id)
VALUES ('$image_Title', '$image_Basename', '$image_Category_Id', $image_Group_Id)
");
}

PHP array for loop

I want to show the array value $result[] from the for loop calculation. However, it shows me nothing on the page. Is there is anything wrong in the below code?
$sql= "SELECT * FROM items where itemID =3 ";
$result1= mysql_query($sql) or die (mysql_error());
while ($row= mysql_fetch_array($result1)){
$quantity[] = $row ['quantity'];
$month[] = $row ['month'];
}
$alpha = 0.3;
for($i = 1; $i > 12; $i++){
$result[$i] = ($quantity[$i] - $result[$i-1]) * $alpha + $result[$i-1];
}
foreach ($result as $key => $value ){
echo "$value";
}
Your for loop has an error. You have
for($i = 1; $i > 12; $i++)
but it should be
for($i = 1; $i < 12; $i++)
This is not directly the answer to your question, but there are few things that hasn't been mentioned that concern the way you query and process your data:
Your SELECT statement doesn't have specific order specified. Since order of records is not preserved you can get records out of correct order and get invalid calculations. Use ORDER BY (e.g. ORDER BY month) or make use of month values and extract exactly previous month's value from array(s) (if it is what you're doing in your code).
Your current code relies on the fact that the resultset from DB will contain (at least) 12 records. If for some reason it will produce less records your for loop will brake.
It's uncertain from the information in the question but it looks like you might need a year in your query unless the table contains records only for one year.
Now, you can calculate the whole thing on DB side with a query like this
SELECT i.month,
COALESCE((i.quantity - p.quantity) * 0.3 + p.quantity, 0) value
FROM items i LEFT JOIN items p
ON i.itemID = p.itemID
AND i.`year` = p.`year`
AND i.month = p.month + 1
WHERE i.itemID = 3
AND i.`year` = 2013
ORDER BY month
SQLFiddle
That's assuming (and I'm not sure about that) you actually need to read previous month's quantity values for your calculations and month column is of integer type
There is an obvious flaw in the logic. You try to get the $i index form $quantity. However, you can't be sure $quantity will have this index.
Supposing that itemId is not the primary key, I would do something like this:
$sql = "SELECT * FROM `items` WHERE `itemID` = 3";
$result1= mysql_query($sql) or die (mysql_error());
while ($row= mysql_fetch_assoc($result1)){
$quantity[] = $row ['quantity'];
}
$alpha = 0.3;
$i = 1
foreach ($quantity as $elem) {
if ($i >= 12)
break;
$result[$i] = ($elem - $result[$i-1]) * $alpha + $result[$i-1];
$i++
}
foreach ($result as $value ){
echo $value;
}

How do I update multiple records in a table with a single MySQL query?

I would like to update multiple records in a MySQL table using a single query. Basically, this is a tasks table, which has assignments for different people on different dates. When these assignments are changed and submitted via the Online form there is a lot of POST data that gets submitted (pretty much all the pending assignments). I've written an algorithm that sorts through all this information and gets what I want out of it, but I'm stuck on writing the query to update the MySQL table:
// Find the modified records and save their information
$update = 0;
for ( $n = 0; $n < $total_records; $n++ )
{
if ( $_POST['update'.$n] == true )
{
$updates_arr[$update] = array( intval($_POST['user_id'.$n]), intval($_POST['task'.$n]), $_POST['date'.$n] );
$update++;
}
}
if ( $mysql_db = OpenDatabase() )
{
$query = "UPDATE tasks_tbl";
if ( $updates_arr[0] )
{
$query .= " SET task = ".$updates_arr[0][1]." WHERE user_id = ".$updates_arr[0][0]." AND date = ".$updates_arr[0][2];
}
for ( $n = 1; $n < $updates; $n++ )
{
$query .= ", SET task = ".$updates_arr[$n][1]." WHERE user_id = ".$updates_arr[$n][0]." AND date = ".$updates_arr[$n][2];
}
$result = mysql_query( $query, $mysql_db );
if ( $result )
{
$page .= "<p>Success!</p>\n\n";
}
else
{
$page .= "<p>Error: ".mysql_error()."</p>\n\n";
}
}
This is the query that is generated:
UPDATE tasks_tbl
SET task = 1
WHERE user_id = 16
AND date = 2010-05-05,
SET task = 1
WHERE user_id = 17
AND date = 2222-02-22
Any suggestions would be appreciated. Thanks.
You can generate a query like this:
UPDATE tasks_tbl SET task=1 WHERE
(user_id=16 AND date='2010-05-05') OR
(user_id=17 AND date='2010-02-22')
There are hacks to avoid using (... and ...) or (... and ...) constructs (concatenate fields and params: "concat(user_id, date) = '". $user_id. $date. "'", but they work a bit slower.
The PHP code:
for ($i = 0; !empty($_POST['update'. $i]; $i++)
if (intval($_POST['task'.$i]) == 1)
$cond[] = '(user_id='. intval($_POST['user_id'. $i]).
' and date=\''. mysql_real_escape_string($_POST['date'.$i]). '\')';
$query = 'UPDATE tasks_tbl SET task=1 WHERE '. implode(' OR ', $cond). ')';
Edit: I don't quite understand why you need to do that in a single query. How many values task can have? 1, 2, 3, or many more? With 3 values, you can use nested IF(...) functions:
UPDATE tasks_tbl SET task=if('. <imploded tasks with value 1>. ', 1, if('.
<tasks with value 2>. ', 2, if('. <tasks with 3>. ', 3,
task))) /* leave as is otherwise */
Or you may put a simple loop on the code I've given:
for ($j = 1; $j <= 3; $j++)
for ($i = 0; !empty($_POST['update'. $i]; $i++)
if (intval($_POST['task'.$i]) == 1)
$cond[] = '(user_id='. intval($_POST['user_id'. $i]).
' and date=\''. mysql_real_escape_string($_POST['date'.$i]). '\')';
mysql_query('UPDATE tasks_tbl SET task=1 WHERE '. implode(' OR ', $cond). ')');
I disagree with your architecture here, but the following should work. Use at your own risk:
UPDATE
Tasks_Table
SET
task =
CASE
WHEN user_id = 16 AND date = 2010-05-05 THEN 1
WHEN user_id = 17 AND date = 2222-02-22 THEN 1
...
END
WHERE
(user_id = 16 AND date = 2010-05-05) OR
(user_id = 17 AND date = 2222-02-22) OR
...
In your example you have task = 1 in all cases, but with the CASE statement you can change them to be what you need for each case. I'll leave the string building to you.
I would prefer to use a prepared query and loop over the data (inside a transaction if needed). That makes it simpler to understand, which is better for maintainability.
Your code smells of sql injection insecurity, too, which prepared queries would eliminate.
See: http://www.php.net/manual/en/mysqli.prepare.php or even better with PDO prepare:
Thanks for the suggestions, everyone. I ended up going with the multiple queries, as it apparently was not going to be as simple to do, as I had hoped.
foreach ( $updates_arr as $record => $data ):
$query = "UPDATE tasks_tbl";
$query .= " SET task = ".$data[1];
$query .= " WHERE task_id = ".$data[0];
$result = mysql_query( $query, $mysql_db );
if ( !$result )
{
break;
}
endforeach;
Are you looking for this:
UPDATE tasks_tbl
SET task = 1
WHERE (user_id = 16 AND date = 2010-05-05)
OR (user_id = 17 AND date = 2222-02-22)
Or you are trying to set 'task' to different values in different rows with a single statement?
The latter is just not possible
I don't think this is possible with one statement. You will need to create separate UPDATE statements:
UPDATE tasks_tbl SET task = 1 WHERE user_id = 16 AND date = 2010-05-05;
UPDATE tasks_tbl SET task = 1 WHERE user_id = 17 AND date = 2222-02-22
You can pass them into mysql_query() as one string separated by ';' if you set mysql to accept multiple queries:
Multiple queries seem to be supported.
You just have to pass flag 65536 as
mysql_connect's 5 parameter
(client_flags)

Categories