MySQL Update and dynamic multiple selection - php

I have form with a multiple selection, which has MySQL table column names as dynamic options.
<select id="rankRights" size="10" class="form-control" name="rights[]" multiple>
<?php
$sql = $pdo->query("SELECT * FROM ranks");
$rights = $sql->fetch(PDO::FETCH_ASSOC);
foreach($rights as $key => $value) {
if($key != 'Name' || $key != 'Id') {
echo "<option value=\"".$key."\"";
if($result[$key] == '1') {
echo " selected";
}
echo "> " . $key . "</option>";
}
}
?>
</select>
And in table there is user rights as columns and value 1 or 0 (means true or false, example below). There can be any number of columns.
.--------------------------------------------------------------------------------.
| Id | Name | ADMIN | ADMIN_EDITUSER | ADMIN_DELETEUSER | etc |
'--------------------------------------------------------------------------------'
| 1 | Admin | 1 | 1 | 1 | ... |
| 2 | Default | 0 | 0 | 0 | ... |
'--------------------------------------------------------------------------------'
What I want to do is update the values to 1 if user has selected column name in multiple selection and vice versa. How can I post those to the PDO query..
EDIT: So, if I submit the form (for example selected ADMIN and ADMIN_EDITUSER from multiple selection), I'll get POST params like rights[]=ADMIN and rights[]=ADMIN_EDITUSER -> in that case I want to update values of columns ADMIN and ADMIN_EDITUSER to 1, and values of all other columns (options not selected) to 0.
I have read following questions and thinking something, but I don't even now know how to do this.

You could create an array of permission/column names:
$names = array('ADMIN','ADMIN_EDITUSER',...);
Initialize permissions to zero:
$permval = array();
foreach ($names as $name)
$permval[$name] = 0;
Walk the posted values to set related permissions:
foreach ($_REQUEST as $key => $value)
{
if ( isset($permval[$key]) )
$permval[$key] = $value;
}
This at least gives you a defined list of values that you use can use to bind to a set of parameters - one for each permission name. Ensure the list of permission names and a statement preparation are kept in sync.
Any easier alternative may be to create a SQL statement on the fly but you may prefer to use PDO.
NOTE: I did not attempt to execute any of the above; it may contain typos!

Related

Foreach loop update sql

I want a loop, that echoes some football matches and my users bets on them, and then the possibillity to change the bets.
I have two tables in my db:
vm_kampe which is the matches where res is the result:
|id |hhold |uhold |res |
|1 |Rusland |Saudi |NULL |
|2 |Egypten |Uruguay |NULL |
... and so on
and vm_kampe, which is the users bets:
|id |resu |
|1 |2-1 |
|2 |1-3 |
... and so on.
My update site is like this:
SELECT * FROM vm_kampe k JOIN vm_207 u ON k.id = u.id
...
foreach($results as $row){
echo '<div class="vm_kupon_row">
<div class="vm_id"><input type="hidden" name="kampids[]" value="'.$row->id.'"></div>
<div class="vm_kampe">'.$row->hhold.' - '.$row->uhold.'</div>
<div class="vm_result"><input class="vm_resultat" type="text" name="resultats['.$row->id.']" placeholder="X-X" value="'.$row->resu.'"></div>
<input type="submit" class="godkend-vm-kupon" name="submit['.$row->id.']" value="Godkend">
My POST site is like this:
$res = $mysqli->real_escape_string($_POST['resultats']);
$id = $mysqli->real_escape_string($_POST['kampids']);
FOREACH ($_POST as $p) {
$gid = $p['id'];
$result = $p['res'];
$sql = "UPDATE vm_207 SET resu = '$result' WHERE id = '$gid'";
};
But if I try editting a bet and press submit, the bet will just stay the same as before. All I want is for me to be able to update every match. Please help :)
UPDATE
I just tried this in the post code:
$id = $_POST['kampids'];
$res = $_POST['resultats'];
foreach ( $id as $key => $k) {
print "The match is " .$k. " and the result is " .$res[$key];
};
I tried writing 2-1 in the first game and the print was:
The match is 1 and the result is 2-1
The match is...
So as I can see, the function works, so now I just need it to update the table..
In your hidden field, you are not setting the index number statically like you are with the other inputs.
<div class="vm_id"><input type="hidden" name="kampids['.$row->id.']" value="'.$row->id.'"></div>
I think this question / answer should help.
How to get form input array into PHP array

PHP Compare column values and edit database accordingly

I am a newbie to PHP and I am stuck at a certain point. I tried looking up a solution for it however, I didn't find exactly what I need.
My goal is to create a leaderboard, in which the values are displayed in descending order plus the rank and score are displayed. Furthermore, it should also display whether or not a tie is present.
The database should look like this:
+---------+------+----------------+-------+------+
| user_id | name | email | score | tied |
+---------+------+----------------+-------+------+
| 1 | SB | sb#gmail.com | 1 | 0 |
+---------+------+----------------+-------+------+
| 2 | AS | as#web.de | 2 | 0 |
+---------+------+----------------+-------+------+
| 3 | BR | br#yahoo.com | 5 | 1 |
+---------+------+----------------+-------+------+
| 4 | PJ | pj#gmail.com | 5 | 1 |
+---------+------+----------------+-------+------+
And the outputted table should look something like this:
+------+-------------+-------+------+
| rank | participant | score | tied |
+------+-------------+-------+------+
| 1 | BR | 5 | Yes |
+------+-------------+-------+------+
| 2 | PJ | 5 | Yes |
+------+-------------+-------+------+
| 3 | AS | 2 | No |
+------+-------------+-------+------+
| 4 | SB | 1 | No |
+------+-------------+-------+------+
I managed to display the rank, participant and the score in the right order. However, I can't bring the tied column to work in the way I want it to. It should change the value, whenever two rows (don't) have the same value.
The table is constructed by creating the <table> and the <thead> in usual html but the <tbody> is created by requiring a php file that creates the table content dynamically.
As one can see in the createTable code I tried to solve this problem by comparing the current row to the previous one. However, this approach only ended in me getting a syntax error. My thought on that would be that I cannot use a php variable in a SQL Query, moreover my knowledge doesn't exceed far enough to fix the problem myself. I didn't find a solution for that by researching as well.
My other concern with that approach would be that it doesn't check all values against all values. It only checks one to the previous one, so it doesn't compare the first one with the third one for example.
My question would be how I could accomplish the task with my approach or, if my approach was completely wrong, how I could come to a solution on another route.
index.php
<table class="table table-hover" id="test">
<thead>
<tr>
<th>Rank</th>
<th>Participant</th>
<th>Score</th>
<th>Tied</th>
</tr>
</thead>
<tbody>
<?php
require("./php/createTable.php");
?>
</tbody>
</table>
createTable.php
<?php
// Connection
$conn = new mysqli('localhost', 'root', '', 'ax');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
// Initalizing of variables
$count = 1;
$previous = '';
while($row = mysqli_fetch_array($result)) {
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
?>
<tr>
<td>
<?php
echo $count;
$count++;
?>
</td>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['score'];?></td>
<td>
<?php
if ($row['tied'] == 0) {
echo 'No';
} else{
echo 'Yes';
}
?>
</td>
</tr>
<?php
}
?>
I think the problem is here
$index = $result['user_id'];
it should be
$index = $row['user_id'];
after updating tied you should retrieve it again from database
So I solved my question by myself, by coming up with a different approach.
First of all I deleted this part:
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
and the previous variable.
My new approach saves the whole table in a new array, gets the duplicate values with the array_count_values() method, proceeds to get the keys with the array_keys() method and updates the database via a SQL Query.
This is the code for the changed part:
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
$query = "SELECT * FROM names ORDER BY score DESC";
$sol = $conn->query("$query");
// initalizing of variables
$count = 1;
$data = array();
// inputs table into an array
while($rows = mysqli_fetch_array($sol)) {
$data[$rows['user_id']] = $rows['score'];
}
// -- Tied Column Sort --
// counts duplicates
$cnt_array = array_count_values($data);
// sets true (1) or false (0) in helper-array ($dup)
$dup = array();
foreach($cnt_array as $key=>$val){
if($val == 1){
$dup[$key] = 0;
}
else{
$dup[$key] = 1;
}
}
// gets keys of duplicates (array_keys()) and updates database accordingly ($update query)
foreach($dup as $key => $val){
if ($val == 1) {
$temp = array_keys($data, $key);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=1 WHERE user_id=$v";
$conn->query($update);
}
} else{
$temp = array_keys($data, $k);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=0 WHERE user_id=$v";
$conn->query($update);
}
}
}
Thank you all for answering and helping me get to the solution.
instead of the update code you've got use something simular
$query = "select score, count(*) as c from names group by score having c > 1";
then you will have the scores which have a tie, update the records with these scores and your done. Make sure to set tie to 0 at first for all rows and then run this solution
UPDATE for an even faster solution sql based:
First reset the database:
$update = "UPDATE names SET tied=0";
$conn->query($update);
All records have a tied = 0 value now. Next update all the records which have a tie
$update = "update docs set tied = 1 where score IN (
select score from docs
group by score having count(*) > 1)";
$conn->query($update);
All records with a tie now have tied = 1 as we select all scores which have two or more records and update all the records with those scores.

INSERT array into separate rows MySQL

I have a dynamic Matrix box where users can unlimited drugs, the data comes through like this:
[addindividuals] => [{"Drug":"Calpol","Strength":"100mg","Form":"Liquid","Quantity":"1"},{"Drug":"Paracetamol","Strength":"200mg","Form":"Tablet","Quantity":"16"}]
What I'm trying to achieve is to have each line inserted into a new row (MySQL) and inserts into their relevant columns like so:
Columns: | Drug | Strength | Form | Quantity
Row1 | Calpol | 100mg | Liquid | 1
Row2 |Paracetamol | 200mg | Tablet | 16
I'm guessing its using the exploded function> (I'm a novice) and then sql to insert the strings?
If you have the values as a json string collection, First you need to explode then the string then use a for each to loop through each string then use another for each to make single row. Please have a below code this may help you.
$addindividuals = '{"Drug":"Calpol","Strength":"100mg","Form":"Liquid","Quantity":"1"},{"Drug":"Paracetamol","Strength":"200mg","Form":"Tablet","Quantity":"16"}';
$exploded_array = explode('},',$addindividuals);
$final_query = "INSERT INTO `table_name` (`Drug`,`Strength`,`Form`,`Quantity`) VALUES ";
$exploded_array[0] = $exploded_array[0].'}';
foreach($exploded_array as $exploded_element)
{
$single_row = '(';
$json_decode = json_decode($exploded_element,true);
foreach($json_decode as $key => $value)
{
$single_row .= "'$value',";
}
$single_row = substr($single_row,0,-1);
$single_row .= '),';
$final_query .= $single_row;
}
$final_query = substr($final_query,0,-1);
echo $final_query;

Search multiple fields MySQL

I have a database like this :
ID | Name | Model | Type
1 | Car | 4 | C
2 | Bar | 2 | B
3 | Car | 4 | D
4 | Car | 3 | D
And a form like this :
Name :
Model :
Type :
Now, I would like to search only the name, for example "Car" and it returns lines 1, 3, 4. (I left Model and Type empty)
If I search "Car" in Name and 4 in Model, it returns lines 1, 3. (I left Type empty)
And if I search "Car" in Name and "D" in Type, it returns line 3, 4 (I left Model empty)
Is it possible to do this in one query ?
This is what I had :
SELECT *
FROM items
WHERE (:name IS NOT NULL AND name = :name)
AND (:model IS NOT NULL AND model = :model)
AND (:type IS NOT NULL AND type = :type)
But it doesn't work.
I would like to fill only 2 on 3 fields and the the "WHERE" adapts and ignore the blank field.
EDIT 1 : It is a little hard to explain but I have a form. I want to have only one required field, the two others are optional but if I also fill the one other or two others fields, they act like a filter.
So the name field is required (in the form). If I fill only the name field, it will select only where name = :name.
If I fill name + model, it will select where name = :name AND model = :model.
and so on...
Thank you for your help.
I'm not sure what you mean by "blank", but assuming you mean NULL, you can do something like this:
SELECT *
FROM items
WHERE (:name IS NULL OR name = :name) AND
(:model IS NULL OR model = :model) AND
(:type IS NULL OR type = :type);
That problem with this query is that it is very hard for MySQL to use indexes for it, because of the or conditions. If you have a large amount of data, and want to use indexes, then you should construct the where clauses based on the parameters that actually have data.
Here's an alternative approach using PHP. You'll need to update the variables.
<?php
$query = 'SELECT *
FROM items
WHERE 1 = 1 ';
//below used for testing can be remove
//$_GET['name'] = 'test';
//$_GET['car'] = 'test2';
//$_GET['type'] = 'test3';
if(!empty($_GET['name'])) {
$query .= ' and name = ? ';
$params[] = $_GET['name'];
}
if(!empty($_GET['car'])) {
$query .= ' and car = ? ';
$params[] = $_GET['car'];
}
if(!empty($_GET['type'])) {
$query .= ' and type = ? ';
$params[] = $_GET['type'];
}
if(!empty($params)) {
$dbh->prepare($query);
$sth->execute($params);
//fetch
} else {
echo 'Missing Values';
}
The 1=1 is so you can append and search field for each field with a value otherwise you'd need to see if it'd already been set.

chained select list with input field - and values taken from database

What I want to achieve:
Insert data into database table using chained select list (the options values ​are ​taken from database table)
Requirement: for the first select list ("tip_cheltuiala"), the available options values must be only the ones that are not used in the rows already inserted (available options are: option 1, 2 and 3; I already inserted rows with option 1 and 3, and now only option 2 must be available)
1. the select list "tip_cheltuiala":
echo '<select name="tip_cheltuiala'.$row_chelt['id_factura'].'" id="tip_cheltuiala'.$row_chelt['id_factura'].'" class="selectContentIncasare">'.$opt_mod_inchidere->TipCheltuiala().'</select>';
and the function for that select list:
class SelectListModInchidere{
public function TipCheltuiala(){
//looking for options that are already in the table
$stmt_chelt_inchisa = $this->conn->prepare('SELECT tip_cheltuiala FROM cheltuieli_mod_inchidere');
$stmt_chelt_inchisa->execute(array());
$results_chelt_inchisa = $stmt_chelt_inchisa->fetchAll();
foreach($results_chelt_inchisa as $row_chelt_inchisa) {
$chelt_inchisa[] = $row_chelt_inchisa['tip_cheltuiala'];
}
print_r($chelt_inchisa); // returns options 1 and 3
for($i=0; $i < count($chelt_inchisa); $i++){
$stmt_tip_chelt = $this->conn->prepare('SELECT * FROM mi_categ_cheltuiala
WHERE tip_cheltuiala <> :chelt_inchisa');
$stmt_tip_chelt->execute(array('chelt_inchisa' => $chelt_inchisa[$i]));
$tip_cheltuiala = '<option value="0">selectati ...</option>';
while($row_tip_chelt = $stmt_tip_chelt->fetch()) {
$tip_cheltuiala .= '<option value="' . $row_tip_chelt['tip_cheltuiala'] . '">' . $row_tip_chelt['tip_cheltuiala'] . '</option>';
}
return $tip_cheltuiala;
}
}
}
$opt_mod_inchidere = new SelectListModInchidere();
There I have the first issue: the select list is populated with option 2 (that is correct) but also with option 3 - I can't figure out why.
2. the select list "mod_inchidere":
returns the option values according with the selected option in select list "tip_cheltuiala
echo '<select name="mod_inchidere'.$row_chelt['id_factura'].'" id="mod_inchidere'.$row_chelt['id_factura'].'" class="selectContentIncasare">
<option value="0">selectati ...</option>
</select>';
and the function for that select list (part of the same class as function TipCheltuiala):
public function ModInchidere(){
$stmt_mod_inch = $this->conn->prepare('SELECT * FROM mi_mod_inchidere WHERE categorie_cheltuiala = :categorie_cheltuiala');
$stmt_mod_inch->execute(array('categorie_cheltuiala' => $_POST['id_categ_cheltuiala']));
$mod_inchidere = '<option value="0">selectati ...</option>';
while($row_mod_inch = $stmt_mod_inch->fetch()) {
$mod_inchidere .= '<option value="' . $row_mod_inch['mod_inchidere'] . '">' . $row_mod_inch['mod_inchidere'] . '</option>';
}
return $mod_inchidere;
}
3. final step: according with the selected option in select list "mod_inchidere, I need to return a value (also stored in database) correlated with the options in select list "mod_inchidre", and put that values in a input field, so the user can (if he wants) modify that value.
At that step I have no idea how to accomplish that.
I can put the value in another select list, but: the user can't modify that value and is not the way to do it.
Please help me with that.
LE
table structures
mi_categ_cheltuiala -> | id | tip_cheltuiala | categorie_cheltuiala |
mi_mod_inchidere -> | id | categorie_cheltuiala | mod_inchidere |
cheltuieli_mod_inchidere (table where I need to insert the data) -> | id | tip_cheltuiala | categorie_cheltuiala | mod_inchidere | valoare |
to get the value that I need to put in the input field I need to interrogate the table "mi_categ_valoare" for the field "mod_inchidere"
mi_categ_valoare -> | id | mod_inchidere | valoare |
$_POST['id_categ_cheltuiala'] -> explanation:
through jQuery I fetch what is selected in this select list "tip_cheltuiala" and send the data to the method TipCheltuiala()
<script type="text/javascript">
$(document).ready(function(){
$("select#mod_inchidere<?php echo $row_chelt['id_factura']; ?>").attr("disabled","disabled");
$("select#tip_cheltuiala<?php echo $row_chelt['id_factura']; ?>").change(function(){
$("select#mod_inchidere<?php echo $row_chelt['id_factura']; ?>").attr("disabled","disabled");
$("select#mod_inchidere<?php echo $row_chelt['id_factura']; ?>").html("<option>asteptati ...</option>");
var id_categ_cheltuiala = $("select#tip_cheltuiala<?php echo $row_chelt['id_factura']; ?> option:selected").attr('value');
$.post("class/select_mod_inchidere.php", {id_categ_cheltuiala:id_categ_cheltuiala}, function(data){
$("select#mod_inchidere<?php echo $row_chelt['id_factura']; ?>").removeAttr("disabled");
$("select#mod_inchidere<?php echo $row_chelt['id_factura']; ?>").html(data);
});
});
</script>
and then I use a service file that will invoke the method TipCheltuiala()
To be honest: Non-English naming conventions making me dizzy :)
Issue: There I have the first issue: the select list is populated with option 2 (that is correct) but also with option 3 - I can't figure out why.
use below single query to get missing tip_cheltuila:
SELECT
tip_cheltuila
FROM
mi_categ_cheltuiala
WHERE
tip_cheltuila NOT IN (SELECT
tip_cheltuiala
FROM
cheltuieli_mod_inchidere);
Need to study other issues...

Categories