I've got this POST form in my website designed to make groups out of an unspecified number users. It works by while looping out all the users in my database with a check box next to their names. You tick the boxes of the users you want, give the group a name then submit the form.
To accomplish the above I need to do two queries due to the way the database has been set up. The table is called Participant/Group and it contains 3 columns: idParticipant, idGroup and GroupName. Here's what I have so far but it has its flaws:
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$pIn = implode("),(", $aParticipants);
$gIn = implode("', '", $aParticipants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`) VALUES ($pIn);");
$query2 = mysql_query("UPDATE `Participant/Group` SET GroupName = '".$_POST['group']."' WHERE idParticipant IN ('$gIn')");
So the first query inserts the id's of the users into the database and the second query adds the group name to each of those newly inserted id's. If you could combine these two queries I think it could solve all my problems but I'm pretty sure the syntax doesn't allow it.
Anyway the problem with the above code is that it overwrites the database with any subsequent overlapping queries. The important thing to remember here is users are not restricted to one group. A user with an id of 7 can be in a Group called Group A and also be in a group called Group C. There will need to be two separate rows to record this. With my code above it is creating the separate rows but both of them will have the group name of whatever was last submitted in the form.
Anyone know how my code could be tweaked (re-written if you want) to fix this?
Add group name in implode
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$group = mysql_real_escape_string($_POST['group']);
$pIn = implode(", {$group}),(", $aParticipants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, `GroupName`) VALUES ($pIn);");
It could be done using only one query. Also, the group field must also be sanitized using mysql_real_escape_string to avoid SQL injection attacks.
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$group = mysql_real_escape_string($_POST['group']);
$sqlvalues = array();
foreach ($aParticipants as $p) {
$sqlvalues[] = "('$p', '$group')";
}
$values = implode(',', $sqlvalues);
mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, GroupName)
VALUES $values");
For the sake of completeness, the best would be to use MySQLi or PDO to take advantage of prepared statements for the sake of performance and security.
$aParticipants = array_map('mysql_real_escape_string', $_POST['check']);
$participants = array();
foreach(aParticipants as $p) {
$participants[] = $p . ', ' . mysql_real_escape_string($_POST['group']);
}
$pIn = implode("),(", $participants);
$query1 = mysql_query("INSERT INTO `Participant/Group` (`idParticipant`, `GroupName`) VALUES ({$pIn})");
EDIT the problem here is that the $iPn string will contain ,( at the end that causes SQL error (which it did not when inserting just one value into one column).
Therefore a line
$pIn = implode("),(", $participants);
has to be replaced by
$pIn = substr(implode("),(", $participants), 0, -3);
Now it should work without any SQL errors...
Related
I have a form that has a checkbox list generated dynamically: name="cursoID[]"
Each value correspond to cursoID ($curso['cursoID']), which is a value taken from a mySQL SELECT query that shows me a list of items IDs.
The user may select N number of items, and I need to take each one of those (ie. $cursoID = $_POST['cursoID'];) in order to save them into an INSERT query.
In the form, I generate each item with a while loop:
<?php
$conectar = mysqli_connect(HOST, USER, PASS, DATABASE);
$query = " SELECT cursoID, nombreCurso, cursoFechaInicio, modalidadCurso, estadoCurso
FROM cursos
WHERE estadoCurso='abierto'";
$buscarCurso = mysqli_query($conectar,$query);
echo '<div class="checkbox">';
while ($curso=mysqli_fetch_assoc($buscarCurso)) {
echo '<input type="checkbox" name="cursoID[]" value="'.$curso['cursoID'].'">'.$curso['nombreCurso'];
}
echo '</div>';
?>
My database consultation in order to insert that field is a simple select:
INSERT INTO cursosUsuarios
(userID, cursoID)
VALUES
('$userID', '$cursoID')
I have no issues with $userID, as is a single value.
How may I use $cursoID = $_POST['cursoID'] to add it to the database? I've been reading some other questions (like this one, or this other one), but couldn't manage to apply it to my case, as I don't know how would I insert it into the database.
I dk how to use mysqli_* so i'll write in PDO. If i could understand correctly this's what u need.
ps: Security ignored.
$cursors = $_POST['cursorID'];
$user = $_POST['user'];
foreach ($cursors as $cursor) {
$query = $DB->prepare('INSERT INTO table (user, cursor) VALUES (:user, :cursor)');
$query->bindValue(':user', $user, PDO::PARAM_INT);
$query->bindValue(':cursor', $cursor, PDO::PARAM_INT);
$query->execute();
}
There's two main ways you can insert a variable amount of data into your database:
Build your query dynamically (if you have many columns, and you don't know how many you'll update)
Like so:
$fields = array();
$values = array();
$fields[] = 'field1';
$fields[] = 'field2';
...
$values[] = 1;
$values[] = 2;
...
$query = 'INSERT INTO table (' . implode(', ', $fields) . ') VALUES (' . implode(',', $values) . ')';
// Execute $query
or:
Add the individual items in separate queries, that you repeat over and over (if you need to fill a variable amount of rows).
Like so (if your checkboxes are named "cursoID[]", the corresponding POST variable will be an array, and you can use anything that'll work with arrays):
$userID_int = (int)$userID;
foreach ($_POST['cursoID'] as $singleID) {
$singleID_int = (int)$singleID;
// Execute: INSERT INTO cursosUsuarios (userID, cursoID) VALUES ('$userID_int', '$singleID_int')
}
However, be very careful - at the moment, your code is vulnerable to SQL injections (for example, if $_POST['cursoID'] is set to something like
'; DROP DATABASE X
you might - depending on your configuration - allow someone to do a lot of nasty stuff, ranging from bypassing your logins to removing your database. As such, I would recommend taking a step back and looking into how you can parameterize your queries, so you don't have to worry about a hostile visitor injecting data in your SQL query. See, for example, this answer.
I need to create a small piece of code to allow me to filter my events database based on category types users have selected.
I currently have it working for users who have only one category selected...
$user_qstring = "SELECT types FROM tbl_users WHERE user_id='".$_SESSION['id']."'";
$user_result = mysql_query($user_qstring);
$user_row = mysql_fetch_array($user_result);
$type_filter = $user_row['types'];
if(isset($type_filter) && $type_filter !="") {
$day_events = "SELECT COUNT(*) FROM tbl_events WHERE day='".$day_id."' AND
type='".$type_filter."'";
}else{
$day_events = "SELECT COUNT(*) FROM tbl_events WHERE day='".$day_id."'";
}
I need to alter this code so that if $type_filter is set and contains multiple categories in the following format.
Festivals,Sports,Education
And have the query automatically add...
OR type='".$type_filter[2]."' OR type='".$type_filter[3]."' OR ect...
I have been able to solve the problem using multiple...
elseif(){
}
Statements, but need a solution that is scalable to unlimited types.
I know I need to start by changing $type_filter to a list using explode...
$type_filter = explode(",", $user_row['types']);
But I'm still having trouble putting it all together for a short elegant solution.
You will need to confirm that $type_filter does not contain single quotes first otherwise you're an easy target for sql injection attacks.
$day_events = "SELECT COUNT(*) FROM tbl_events WHERE day='".$day_id."' AND type IN ('" . implode("','", explode(',', $type_filter)) . "')";
try something like the follwing sql
select * from ... where type in ('one', 'two', ...) ...
and as a remark - always escape get/post data using mysql_real_escape_string or you are vulnerable to injection attacks.
I'm afraid this is going to sound redundant. I have done my diligence, and substituted at least three ideas I've found so far, and nothing works.
The goal is to merge unique fields from two tables, but right now I can't even get identical fields from one table into another that was created as an identical table. Here is the code so far, with my comments:
$result = mysql_query("SELECT * from $db.$tbl LIMIT 50");
if($result) {
while($maindata = mysql_fetch_assoc($result)) {
$newdata = implode ("," , $maindata);
$newdata = mysql_escape_string($newdata);
$pop = "INSERT INTO $db.address_new (id,entitynum,address,city,state,zip,country,remarks)
SELECT FROM $db.address";
//This is the original code replaced by the above
//$pop = "INSERT INTO $db.address_new (id,entitynum,address,city,state,zip,country,remarks)
// VALUES ($newdata)";
mysql_query($pop);
//print_r($pop);
//Seems to give the correct output in the browser, but the table address_new remains empty. `
Thank you in advance. I really appreciate your help.
To directly insert from another table (note: if ID is auto_increment you may or may not want to insert it this way):
INSERT INTO db.address_new (id,entitynum,address,city,state,zip,country,remarks)
SELECT (id,entitynum,address,city,state,zip,country,remarks)
FROM db.address LIMIT 50
(do not put this in a loop)
If you're looking for unique values, you can do that a couple of ways. Personally, I would have a unique key on one (or a set of) the values and then just do INSERT IGNORE:
INSERT IGNORE INTO db.address_new
(id,entitynum,address,city,state,zip,country,remarks)
SELECT (id,entitynum,address,city,state,zip,country,remarks)
FROM db.address LIMIT 50
As a side note:
// use mysql_real_escape_string
mysql_escape_string($newdata);
// since you're passing this through PHP, you need to make sure to quote
// all of your values. This probably means you'll need to loop and replace this
// $newdata = implode ("," , $maindata);
// with something like:
$newdata = array();
foreach( $maindata as $column )
{
$newdata[] = "'" . mysql_real_escape_string( $column ) . "'";
}
$newdata = implode(',', $newdata);
// you're missing the columns in your select clause.
$pop = "INSERT INTO $db.address_new ".
"(id,entitynum,address,city,state,zip,country,remarks) ".
// You need to select *something*
"SELECT FROM $db.address";
I'm not sure how to accomplish this issue which has been confusing me for a few days. I have a form that updates a user record in MySQL when a checkbox is checked. Now, this is how my form does this:
if (isset($_POST['Update'])) {
$paymentr = $_POST['paymentr']; //put checkboxes array into variable
$paymentr2 = implode(', ', $paymentr); //implode array for mysql
$query = "UPDATE transactions SET paymentreceived=NULL";
$result = mysql_query($query);
$query = "UPDATE transactions SET paymentdate='0000-00-00'";
$result = mysql_query($query);
$query = "UPDATE transactions SET paymentreceived='Yes' WHERE id IN ($paymentr2)";
$result = mysql_query($query);
$query = "UPDATE transactions SET paymentdate=NOW() WHERE id IN ($paymentr2)";
$result = mysql_query($query);
foreach ($paymentr as $v) { //should collect last updated records and put them into variable for emailing.
$query = "SELECT id, refid, affid FROM transactions WHERE id = '$v'";
$result = mysql_query($query) or die("Query Failed: ".mysql_errno()." - ".mysql_error()."<BR>\n$query<BR>\n");
$trans = mysql_fetch_array($result, MYSQL_ASSOC);
$transactions .= '<br>User ID:'.$trans['id'].' -- '.$trans['refid'].' -- '.$trans['affid'].'<br>';
}
}
Unfortunately, it then updates ALL the user records with the latest date which is not what I want it to do. The alternative I thought of was, via Javascript, giving the checkbox a value that would be dynamically updated when the user selected it. Then, only THOSE checkboxes would be put into the array. Is this possible? Is there a better solution? I'm not even sure I could wrap my brain around how to do that WITH Javascript. Does the answer perhaps lie in how my mysql code is written?
--
Edit: Ok, just more information. The SQL Queries I have going on - the first two are to wipe everything clean (in case a checkbox is UNCHECKED) and then next they are updating the SQL queries based on which checkboxes are checked upon post.
However, I'm thinking this is a bad way to do it. Why force the database to first wipe out ALL data for paymetreceived, paymetdate? The problem with this, also, is that *all the subsequent checkboxes, regardless of how long ago they were checked, get updated in the SQL query as it is now.*There's got to be a way to update it better. I'm just not sure HOW to do it. any ideas?
You are not filtering by id in this queries:
$query = "UPDATE transactions SET paymentreceived=NULL";
$query = "UPDATE transactions SET paymentdate='0000-00-00'";
Try adding: WHERE id IN ($paymentr2)";
The problem is in your first 2 sql UPDATE statements. You don't provide a WHERE clause, so that's going to update all your records. You could add:
WHERE id IN ($paymentr2)
to your first two UPDATE statements
I'm trying to update multiple rows in one table in MySQL database by doing this. And its not working.
$query = "UPDATE cart SET cart_qty='300' WHERE cart_id = '21';
UPDATE cart SET cart_qty='200' WHERE cart_id = '23';
UPDATE cart SET cart_qty='100' WHERE cart_id = '24';";
mysql_query($query,$link);// $link is specified above
Anyone know what is wrong with this.
From the PHP documentation:
mysql_query() sends a unique query (multiple queries are not supported)
The ; separates SQL statements, so you need to separate the queries if you want to continue using the mysql_query function...
mysql_query can't use multiple queries.
The easiest thing is to just run them separately. I believe you can do multi query but I haven't tried it.
$updateArray = array(21=>300,23=>200,24=>100);
foreach($updateArray as $id=>$value)
{
$query = "UPDATE cart SET cart_qty='$value' WHERE cart_id = '$id'";
mysql_query($query,$link);// $link is specified above
}
This will accept a combination of IDs and their corresponding cart value. Looping though, it builds the query and executes it. The array can then come from a variety of sources (results from another query, form inputs or, as in this case, hard-coded values)
Update:
If you really need to execute all in one, heres the PHP info on multi query:
mysqli::multi_query
You can do it this way:
UPDATE table
SET col1 = CASE id
WHEN id1 THEN id1_v1,
WHEN id2 THEN id2_v1
END
col2 = CASE id
WHEN id1 THEN id1_v2,
WHEN id2 THEN id2_v2
END
WHERE id IN (id1, id2)
This example shows updating two different columns in two different rows so you can expand this to more rows and columns by cludging together a query like this. There might be some scaling issues that makes the case statement unsuitable for a very large number of rows.
You'll need to send them as separate queries. Why not add the queries as strings to an array, then iterate through that array sending each query separtely?
Also check this thread for another idea
This isn't the best method.. But if you need to do multiple queries you could use something like...
function multiQuery($sql)
{
$query_arr = explode(';', $sql);
foreach ($query_arr as $query)
{
mysql_query($query);
}
}
another example of a helper query
function build_sql_update($table, $data, $where)
{
$sql = '';
foreach($data as $field => $item)
{
$sql .= "`$table`.`$field` = '".mysql_real_escape_string($item)."',";
}
// remove trailing ,
$sql = rtrim($sql, ',');
return 'UPDATE `' . $table .'` SET '.$sql . ' WHERE ' .$where;
}
echo build_sql_update('cart', array('cart_qty' => 1), 'cart_id=21');