Retrieving and inserting multiple entries in MySQL/PHP - php

I'm trying to create a form that retrieves data from a database and then allows me to add data to one column for multiple entries.
Every entry has an ID, a lot of other fields, and a category. I am trying to add these categories for every ID in the database using one form.
I came up with the solution below, but (of course)this only inserts the LAST entry in the form, because the variable ID is changed with every new row.
The form I have now shows me what I want to see, but it does not save it the way I need it to.
The question is, (how) can I make a form that has all entries in the database with a dropdown menu next to it,
lets me select the right category from the dropdown, and save it to the database?
The form:
$result = mysqli_query($con,"SELECT * FROM aw");
while($row = mysqli_fetch_array($result))
{
echo '<tr><td><input type="hidden" name="ID" value="'.$row[ID].'."> '.$row[ID].'</td><td>';
echo '
<select name="cat" onchange="this.form.submit()">
<option value="C1">category1</option>
<option value="C2"">category2</option>
</select></td></tr>
';
}
?>
<tr><td><input type="submit" title="SAVE" ></td></tr>
</form>
The insert.php
$sql="REPLACE INTO aw (ID,cat)
VALUES
('$_POST[ID]','$_POST[cat]')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
mysqli_close($con);
?>
I changed my code according to Tom's answer and I now have the following:
This does print the values like they should be, but it still saves only the last entry into the database. I'm sure I must be missing something here..
$name = $_POST['ID'];
$category = $_POST['cat'];
foreach( $name as $key => $n ) {
$sql="REPLACE INTO aw (ID,cat)
VALUES
('$n','$category[$key]')";
print "The id is ".$n.", category is ".$category[$key]."<br>";
}

First of all, use PDO::Mysql, the SQL functions you are using are a bit deprecated and do not focus much on security. At the moment your code is vulnerable to SQL injections and your output is sensitive to XSS attacks (always sanitize output).
I was wrong, MySQL is deprecated but MySQLi is not! I do prefer using PDO::Mysql because of the range of databases it supports (MySQLi only supports a MySQL database, PDO::Mysql supports many more)
Now to your original question, you can create a sort of array. By making name="ID" to name="ID[]" and name="cat" to name="cat[]".
Now you can do
$name = $_POST['ID'];
$category = $_POST['cat'];
foreach( $name as $key => $n ) {
print "The id is ".$n.", category is ".$category[$key];
}

The problem is your using the name elements regardless of how many rows..
So name="ID" & name="cat" needs to change on each row or have an array type
you could use something like name="ID[]" as this would append/ create an array to $_POST['ID']... but you still would want to change your SQL query to handle each of these.
EDIT
If i understand, you want to be able to identify a row from the table so you can use that in the database?? One way todo this is when creating the table.. Give the TR a id/name attribute that is the row id from the database.
Then can simply know by checking that if your using the select menu from row #4, you check the id/name attribute of the current row and you have your database id.
<tr id='my_row_1'>
<td class='colName'>John</td>
<td class='colPhone'>1111</td>
<td class='colOther'>....</td>
</tr>
<tr id='my_row_2'>
<td class='colName'>Bill</td>
<td class='colPhone'>2222</td>
<td class='colOther'>....</td>
</tr>
<tr id='my_row_3'>
<td class='colName'>Roger</td>
<td class='colPhone'>3333</td>
<td class='colOther'>....</td>
</tr>
With something like the above, Say i had a button in on of the columns... When i click on that button.. all i have todo is find the parent TR and get its id value.... Then explode it by "_" and get the last piece to have the id..
So your PHP would generate the id easily... Also, using a form would not be the best case here.. Using multiple forms within a table is... wasteful... sort of ..
I would suggest more so, having a button that simple calls a js function which will then post/ajax/jquery what you need from that row.
--- Trying to understand exactly what you need??

Related

How to INSERT multiple rows with multiple values, but only for items that have checkboxes ticked next to them

I am coding a discography tool for a music database.
Artists are able to insert tracks, singles, EPs, and albums all into separate tables on the database.
Having tracks be in their own separate table allows the same tracks to be attached to multiple singles, EPs and albums while only requiring there to be one record for that track in the database.
Which means individual track pages can have an automatically generated list of links back to the Singles, EPs and albums that they appear on. Making navigating the database through the website a much smoother experience.
I have come to the point where I am coding a tool to attach any existing tracks in the database for a given artist onto an album page.
I am using another table in the database called 'trackconnections' to create the relational links between the track ids from the track table and the album id from the album table, with an additional column called albumtracknum available to be able to output the tracks in the right order when queried on the album page.
The code for the tool is behind a button labelled 'Attach existing track(s) to album'. The code for this tool is as follows:
if (isset($_POST['attachexistingtracktoalbum-submit'])) {
require "includes/db_connect.pdo.php";
$artistid = $_POST["artistid"];
$albumid = $_POST["albumid"];
echo '<strong>Select each track you would like to add to this album below and type in the track number you want it to have on the album in the box underneith the name of each selected track.</strong><br><br>';
$stmt = $pdo->query("SELECT * FROM track WHERE artist_id = '$artistid'
order by trackname");
while ($row = $stmt->fetch())
{
echo '<form action="includes/attachexistingtracktoalbum.inc.php" method = "post">';
echo '<div class="checkbox">';
echo '<label>';
echo "<input type='checkbox' name='trackid[]' value='".$row['id']."' />";
echo '<span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span>';
echo ' '.$row['trackname'];
echo '</label>';
echo "<br><label for='albumtracknum'>Track number:</label><br>
<input type='text' name='albumtracknum[]'>
<input type='hidden' name='albumid[]' value='".$albumid,"'>
<br><br>";
echo '</div>';
}
?>
<input type="hidden" name="albumidforreturn" value="<?php echo $albumid;?>">
<button type="submit" name="attachexistingtracktoalbum-submit">Attach track(s) to album</button>
<?php }
else {
header("Location: /index.php");
exit();
}?>
(NB: The post data here is not sanitised for the sql query as it has been passed along in a hidden form from the original album page)
This generates a page with all track names for the current artist available on a list with checkboxes, with each track name being followed by a data entry box to enter the track number for the album being added to.
Submission of the form then hands off to the following include code:
if (isset($_POST['attachexistingtracktoalbum-submit'])) {
require "db_connect.pdo.php";
$albumid = implode(',',$_POST['albumid']);
$trackid = implode(',',$_POST['trackid']);
$albumtracknum = implode(',',$_POST['albumtracknum']);
$albumidforreturn = $_POST['albumidforreturn'];
// echo 'albumid: '.$albumid.'<br>';
// echo 'trackid: '.$trackid.'<br>';
// echo 'albumtracknum: '.$albumtracknum.'<br>';
$sql = "INSERT INTO trackconnections (albumid, trackid, albumtracknum) VALUES (?,?,?);";
$stmt= $pdo->prepare($sql);
$stmt->execute([$albumid,$trackid,$albumtracknum]);
header("Location: ../albumdetail.php?albumid=$albumidforreturn");
exit();
}
else {
header("Location: ../index.php");
exit();
}
(NB: The commented out echos are there to test what the output is from the previous form)
The 2 problems I am having are that my 'Attach existing tracks to album' form submit:
1. Passes on too much data.
The generated form should only pass on the track ids, album number, and track numbers that have had their checkboxes ticked. For insertion into the 'trackconnections' table.
Instead it narrows down the ticked checkbox track ids only and then creates comma separated values for every available track to select, rather than just those actually selected.
Which leads to annoying outputs such as the following when passing on data from form to include:
albumid: 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
trackid: 30,14
albumtracknum: ,2,3,,,,,,,,,,,,,,,,,,,,,
Where it should only read as:
albumid: 4,4
trackid: 30,14
albumtracknum: 2,3
Having too much data get passed through means that the row inserts won't be correct on multiple INSERTS once I do get this working, as they won't align with one another in the correct order.
2. The include only INSERTS 1 row to the 'trackconnections' table.
It seems I am misunderstanding how to add multiple rows to the database with my code here.
As having multiple checkboxes ticked on my 'Attach existing tracks to album' form only inserts 1 single row to the database on submission of the form each time.
Consistently the only track that gets added to the 'trackconnections' table is the first track with its checkbox ticked and, because of issue no. 1 above, the albumtracknum is always 0 unless I type a number into the first albumtracknum box on the available checklist.
I need to make tweaks to this code so that both problem 1 and 2 are addressed together, meaning that ticking the checkboxes & adding track numbers into each box following the track names actually adds multiple rows to the database along with their corresponding album track numbers.
I hope someone can help.
EDIT TO SHOW REFINED AND WORKING CODE:
New code for checkbox and textbox sections -
if (isset($_POST['attachexistingtracktoalbum-submit'])) {
require "includes/db_connect.pdo.php";
$artistid = $_POST["artistid"];
$albumid = $_POST["albumid"];
echo '<strong>Select each track you would like to add to this album below and type in the track number you want it to have on the album in the box underneith the name of each selected track.</strong><br><br>';
$stmt = $pdo->query("SELECT * FROM track WHERE artist_id = '$artistid'
order by trackname");
echo '<form action="includes/attachexistingtracktoalbum.inc.php" method = "post">';
while ($row = $stmt->fetch())
{
echo '<div class="checkbox">';
echo '<label>';
echo "<input type='checkbox' name='trackid[]' value='".$row['id']."' />";
echo '<span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span>';
echo ' '.$row['trackname'];
echo '</label>';
echo "<br><label for='albumtracknumber'>Track number:</label><br>
<input type='text' name='albumtracknumber_".$row['id']."'>
<input type='hidden' name='albumid[]' value='".$albumid,"'>
<br><br>";
echo '</div>';
}
?>
<input type="hidden" name="albumidforreturn" value="<?php echo $albumid;?>">
<button type="submit" name="attachexistingtracktoalbum-submit">Attach track(s) to album</button>
</form>
<?php }
else {
header("Location: /index.php");
exit();
}
New code for the include INSERT processing -
if (isset($_POST['attachexistingtracktoalbum-submit'])) {
require "db_connect.pdo.php";
$albumid = implode(',',$_POST['albumid']);
$trackid = implode(',',$_POST['trackid']);
$albumidforreturn = $_POST['albumidforreturn'];
foreach($_POST['trackid'] as $trackidloop) {
$albumtracknum = $_POST["albumtracknumber_{$trackidloop}"];
$sql = "INSERT INTO trackconnections (albumid, trackid, albumtracknum) VALUES (?,?,?);";
$stmt= $pdo->prepare($sql);
$stmt->execute([$albumid,$trackidloop,$albumtracknum]);
}
header("Location: ../albumdetail.php?albumid=$albumidforreturn");
exit();
}
else {
header("Location: ../index.php");
exit();
}
This isn't an entire solution but I see some problems:
You are looping through tracks and creating a new form for each one. The first problem is , you are missing the closing form tag. I guess the browser is automatically creating one, when it sees the next form start tag. ?? That's why you only get one single posted checkbox.
I would put all the track checkboxes into a single form. Then the posted trackid[] array will contain all the checked items.
[EDIT after your comment: The hidden fields albumid[] post the entire array, whereas the trackid[] checkboxes only post the actual checked boxes (HTML spec).
Instead of having albumid[], You could put the trackID and albumID together for the checkbox value, then parse them apart when you handle the post:
$value = $row['id']. ',' . $row['albumid'];
echo "<input type='checkbox' name='trackid[]' value='".$value."' />";
ALSO, the SQL, "INSERT INTO (..) .. VALUES (...) " only inserts one row.
It's easy to do that SQL in a loop for all the checked boxes.
foreach($_POST['trackid'] as $value) {
// parse the $value...
// SQL Insert...
}
EDIT 2: From my own comment:
Like hidden fields, input (text) field arrays also post the entire array (with empty values for blank inputs). (Again, this is not a PHP thing, it's a web browser standard to only post checked checkboxes and radio buttons. But ALL text and hidden INPUTs are posted.) So in your example, you need to code a mechanism to know which textbox goes with each checkbox. Quick and dirty...You could add a row index (0,1,2,3...) as another comma-separated number in your checkbox values, then you'll have the index into the posted textbox array. Alternatively, you could name the textboxes ' .. name="textinput_' . $row['trackid'] . '" ...' (not an array), then upon post, read them in your foreach loop with
$val = $_POST["textinput_{$trackid}"];

populate html table in PHP

I am at the end of my project, I have all the data from my database and everything is working fine I just can not work out how to display it in a table.
I have generated a table which is the (number of projects) * (the number of people).
The data I have collected is user_id, project_id and hours.
But how do I insert '6' (hours) into user_x's row in the column of the correct project?
I can only think to make x arrays (for the number of projects) of the length for the number of users and evaluate the project code to select the correct array and then use the user id to get the correct position to place the value and simply spit out the array into the td tag
This is incredibly messy, I wonder if I'm going about it completely wrong.
If this is indeed the best way I need to recursively create arrays and write code which references variables that might not even exist. Sounds insane to me
//for the length of projects create arrays that are the length of users and fill with 0's
for ($v = 0; $v < $rows_x; $v++){
$name = "variable{$v}";
$$name = array_fill(0, $rows_u, '0');
EDIT: What I am trying to do is show the number of hours that are booked to projects between two dates. I have gotten all the data correctly but now I need the data to land into a table so you can easily see which user booked to what project.
In an excel world I could use the project number to select the Y axis and the user id to select the X axis. However I don't know the best way to do this in php.
Surely creating an array for each project the length of the users and filling with data if there is data is not the best way.
I don't know if this is what you're looking for, but I insert my values into a table in the process of retrieving them.
You can echo the values into a <td> as long as they are in your SQL SELECT statement.
<table>
<thead>
<tr>
<th>Values1</th>
<th>Values2</th>
</tr>
</thead>
<tbody>
<?php
$sql = "SELECT value1, value2
FROM tbl_Values";
if (!$res = $link->query($sql)) {
trigger_error('Error in query ' . $link->error);
} else {
while ($row = $res->fetch_assoc()) {
?>
<tr>
<td>
<?php echo $row['value1']; ?>
</td>
<td>
<?php echo $row['value2']; ?>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
This is the way I put data into my tables, without using arrays.

Trying to copy data to a table with checkboxes, a form, and php

My webpage is pulling data from two tables - applications and archiveapps - and displays them using the following:
$sql = "SELECT * FROM applications";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "Lots of info, including some html thrown in for style."
I want users to be able to click a checkbox listed next to each row and then hit an "Archive Selections" button that then moves all the selected entries from the applications table to the archiveapps one.
So far I've tried a form with it's code half in the echo above (so that a checkbox would go by each listed row from the $sql query) with the submit button outside (so that there would only be one "Archive Selections" button) but I'm sure this isn't proper syntax.
To actually move the data, I had this for the checkbox:
<form method='post' action=''><input type='checkbox' name='archname' value=".$row["charname"].">
(The above was inside an echo statement, so I assume it was able to pull the $row["charname"] no problem, but am unsure how to verify that.)
A little further down the page is the submit button and </form>.
And then I've got the function I want it to run when the submit button is clicked, to check if boxes have been selected and copy them into the archiveapps table. I'm sure there's something I'm missing here, probably in referencing what exactly is selected, and then copying that row's data to the other table... but honestly I just don't know enough about php to know what I'm missing.
if(!empty($_POST['archname'])) {
foreach($_POST['archname'] as $check) {
function archiveapp() {
$sqli="INSERT INTO archiveapps SELECT * FROM applications";
if ($conn->query($sqli) === TRUE) {
echo "<i>Archived</i>";
} else {
echo "Error: " . $sqli . "<br>" . $conn->error;
}}}}
Most of this has just been gathered from google searches and kind of mushed together, so I'm sure there are a lot of things done wrong. Any pointers or advice would be greatly appreciated!
Oh and my end goal is to copy the data to the archiveapps table and then delete it from the applications table, but for now I've just been focusing on the copying part, since I assume deleting a row will be fairly simple? Either way it's not the priority for this question.
Thanks in advance for any help!
Use a tool like FireBug to see what you are actually posting to server. You have multiple checkboxes with the same name, so you are sending only 1 value (the last checked, I think).
You need to send all of them, so use brackets after the name:
<!-- this is just an example -->
<input type="checkbox" name="archname[]" value="1">
<input type="checkbox" name="archname[]" value="2" checked>
<input type="checkbox" name="archname[]" value="3" checked>
Then on PHP, inside $_POST['archname'] you will get this:
Array(2, 3)
After this, you can do a foreach(...) loop like you are already doing, inserting only the ID you get from the $_POST variable:
foreach($_POST['archname'] as $id){
$sqli = "INSERT INTO archiveapps (id) VALUES (".(int)$id.")";
}

mysql query not working in php?

My mysql table has 6 fields bkid bkname bkauth bkpub bkedn bkstock.
This program is just for testing you may see some extra lines which I have commented out because I am not using the commented lines for now.
Just for now I am trying to get bkid from the html form and then use it in a query to find out the last column of the retrieved result in $row as $row[5] which is books in stock bkstock. So,I need to find out the no of books in stock from the bkid provided by the user in the form and clicking the button to submit the form.
The query given below does not work.
Notice: Undefined offset: 5 in C:\xampp\htdocs\projects\library\incstockbook.php on line 41
<HTML>
<HEAD>
<h1 align="center">THIS PAGE ADDS STOCK OF BOOKS TO THE LIBRARY</h1>
</HEAD>
TO INCREASE THE STOCK OF BOOKS TO INCLUDE TO THE LIBRARY
<FORM action="incstockbook.php" method="POST">
<table>
<tr>
<td>ENTER THE BOOK ID :</td>
<td><input type=text name="bkid">
</TR>
<TR>
<td>ENTER THE NO. OF BOOKS TO INCLUDE TO THE LIBRARY:</td>
<td><input type=text name="bkstock">
</tr>
</table>
<BR>
CLICK HERE STOCK MORE BOOK :<input type="submit" value="ADD STOCK" name="submit"></br></br>
</FORM>
<?php
$server="localhost";
$username="root";
$password="pramit";
$db="test";
$mysqli = new mysqli($server,$username,$password);
if ($mysqli->errno)
{
printf("Unable to connect to the database:<br /> %s",
$mysqli->error);
exit();
}
$mysqli->select_db($db);
$query1 = "select bkstock from books where bkid=";
if(isset($_POST['submit']))
{
$bkid=$_POST['bkid'];
// $bkstock=$_POST['bkstock'];
$query1.="'$bkid'";
$result=$mysqli->query($query1,MYSQLI_STORE_RESULT);
$row = $result->fetch_array(MYSQLI_NUM);
echo "$row[5]";
}
$mysqli_close;
?>
First thing to do in such cases is to use var_dump(). It'll tell you what is in $row variable and allow you to fix that problem. And problem is the fact that you're trying to get sixth item from row when there is only one, so it should be $row[0].
But there are some more to fix here.
Check $mysqli_close; statement, maybe you wanted to use $mysqli->close()? Because like that it doesn't make any sense.
Next, never use raw user input data in queries. It's dangerous! You have to filter it, or better use prepared statements.
$row[5] tries to retrieve the 6th element from your array. Since this row maps to 1 row (the first) of your query result, the number of elements contained in the row is exactly the number of selected columns from your table. select bkstock from... indicates there will only be one element in your array, so only $row[0] will work.
And as an extra: there is no need to wrap it in a quote when you echo it. just echo $row[0]; should be fine.

Processing a form created by dynamic php/mySql Setup

I run a script to create an order form, this is just a really small sample. I'm not so good with PHP and dynamic forms. It pulls data from mysql database.
<td>
<h3>Round Cuts</h3>
<?php while($row = mysql_fetch_array($round_cuts)){
$round_box_value = #$row["meat_names"];
$round_box_value_name = #$row["meat_names"];
echo " <input type=\"checkbox\" name=\"round_box_value\" value=\"$round_box_value_name\"> $round_box_value_name";
echo "<br>";
}?>
</td>
I've ever really only built basic contact forms, how could I process a dynamic form like this. If all else fails I would just take all the possible elements and program this like it was a not dynamic. There must be a better way though.
Even a link to a website would be helpful. I've been searching for a solution. Thanks.
I'll assume your table as a primary key of id
Start off with a minor change to your checkboxes:
<?php
while($row = mysql_fetch_array($round_cuts)){
echo sprintf('<label><input type="checkbox" name="round_box_value[]" value="%s"> %s</label><br>', $row['id'], $row['meat_names']);
}
?>
The name now has an [] at the end to tell php it's an array of values + I've wrapped the checkbox in a label for convenience.
Then when you process the form, you can simply iterate through round_box_value like so
<?php
foreach ($_POST['round_box_value'] as $id) {
// $id is the table reference from your previous table
}
// or query all the rows selected
$ids = array_map('intval', $_POST['round_box_value']); // "basic" sql injection handler
$sql = "SELECT * FROM table WHERE id IN (".implode(",", $ids).")";
should produce something like:
SELECT * FROM table WHERE id IN (2,5,7)

Categories