Problem Regarding Updating Values using Foreach - php

This is the input fields
<?php while($educationalQualificationsFromDB = Database::fetchData($queryForEducationalQualifications))
{
$eduQualifcationId = $educationalQualificationsFromDB['education_qualification_id'];
$eduQualifcation = $educationalQualificationsFromDB['edu_qualification'];
echo "<input class='form-control' type='text' name='eduqualification[]' value='$eduQualifcation'>";
echo "<br>";
}
?>
This is the query I used,
$eduQualifications = $_POST['eduqualification'];
foreach($eduQualifications as $oneEduQualifications)
{
Database::query("UPDATE educational_qualification SET edu_qualification = '$oneEduQualifications'");
}
I'll simply explain like this there are multiple values coming from the database from the educational qualifications table.I have used a while loop to fetch them all inside inputs.And there are several inputs right.So I need a condition to update all those relevant database data.I used foreach loop to fetch data from the inputs cause i used the name of the input fields as an array.When I update them using foreach loop it update all records with the same name.Please explain me why such thing happened and give me a solution to update all relevant multiple database values with the relevant input values.

An UPDATE query will update all rows, unless constrained to specific rows by a WHERE clause. So you'll need to add something like:
UPDATE educational_qualification
SET edu_qualification = '$oneEduQualifications'
WHERE education_qualification_id = '$eduQualifcationId'
So you need to transport the $eduQualifcationId through the form together with the $eduQualifcation as well. The best way for that is to just use it as the $_POST array key:
<input type='text' name='eduqualification[$eduQualifcationId]' value='$eduQualifcation'>
Now your $_POST array will look something like:
array(
'eduqualification' => array(
'42' => '69'
)
)
So you can do:
foreach ($_POST['eduqualification'] as $id => $qualification) {
Database::query("UPDATE educational_qualification SET edu_qualification = '$qualification' WHERE education_qualification_id = '$id'");
}
As is, you appear to be open to both SQL and HTML injection BTW, which you'll want to fix:
How can I prevent SQL injection in PHP?
How to prevent XSS with HTML/PHP?
If you have multiple users, and certain users should only be allowed to update their own data, then you'll want even more constrains and checks, something like:
UPDATE educational_qualification
SET edu_qualification = '$oneEduQualifications'
WHERE education_qualification_id = '$eduQualifcationId'
AND user = '$current_user'
Because POST requests are just HTTP requests, and anyone can send any arbitrary data in an HTTP request…

Related

Update db tables of only updated fields of form- JQuery, PhP

I have a huge multistep form with data for multiple tables in mysql db. For every field my html is like-
input type="text" name="names" value="" // value set using php echo
On submit at php I am doing this for all the fields of my form-
$name=$_POST['names'] ?? ' '
to avoid unidentified index and unidentified variable
Then i update my first table and write log that its updated.
$query=mysqli_query($con,"UPDATE teacherpersonal set name='$name' ... where id=$id");
write_mysql_log("teacherpersonal updated", "facultydetails", $id).
I have defined write_mysql_log.
And similarly i update all the remaining tables with either the updated values or blank ("") values.
Since you can see that update query always executes even if the fields are not changed. Hence it is always logged that the tables are updated. But that's not what I want. I want to update only those fields in the table which are changed and remaining stay intact and log only those tables which are thus updated. Many tables won't be updated this way as the user might change only few details.
Using jquery and php.
My write_mysql_log is
function write_mysql_log($message, $db, $faculty_id)
{
$con=mysqli_connect("localhost","root","");
mysqli_select_db($con,"facultydetails");
// Construct query
$sql = "INSERT INTO my_log (message, faculty_id) VALUES('$message', '$faculty_id')";
$query=mysqli_query($con, $sql);
// Execute query and save data
if($query) {
echo 'written to the database';
}
else {
echo 'Unable to write to the database';
}
}
This you can achieve in 2 different ways.
1) With the help of jQuery check the values which are updated, post only those values to the php script
2)At the time of updating the check the current values with the updated one based on that criteria update the db tables.
solution 1 is less time taking process compare to the other.
You need to update only the user edited value, by doing this you can achieve it;
$oldvalue = array("username" => "green", "email" => "green#mail.com","dob" => "111");
$newvalue = array( "email" => "green#mail.com","dob" => "111","username" => "blue");
$updates = array_diff($newvalue, $oldvalue);
$implodeArray = implode(', ', $updates);
$sql = ("UPDATE user WHERE userID=$userID SET $implodeArray");
mysql_query($sql,$this->_db) or die(mysql_error());
mysql_close();
Output:
$updates = array_diff($newvalue, $oldvalue);
will have:
Array ( [username] => blue )
which is changed one
Ok after considering many options like-
create json object for old and new data and then compare and check which values changed and update that table and log it.
Or create a php array with old and new data and check diff then do the same (as suggested by Ram Karuppaiah)
Or a bad idea to have a flag on every input and then mark which ones have changed using onkeyup jquery event then try to update only those fields tables.
So finally what i did is that i let the form get submitted with all the data. As earlier i am taking the data in php as $name=$_POST['names'] ?? ' ' (blank if nothing is submitted or if something submitted then its value).
Before update statement in php, i am querying the table and comparing the database values with the values i got, if all same i dont do anything. If not then i update the table with the new values and log the change.

querying db for get-variable with multiple values

I have checkboxes that represent the condition of a product. When a user checks for example Excellent, the value 1 is stored in a GET-variable like this:
...index.php?condition=1
Now, when the user checks multiple boxes (which has to be possible), it looks like this:
...index.php?condition=1,2,3
Obviously, I have to query my database in order to show the products corresponding to the user's choice(s).
if the user only checks one box, the statement is simple:
if (!empty($_GET['condition'])){
$sql = $sql . " AND (Condition = '".$_GET['condition']."')";
}
But what if the user checks multiple boxes? How would the statement have to look? (is it even possible to solve it this way?
thanks!
This is the script that creates the address:
<script>
$('#condition_select input:checkbox').change(function() {
var condition = $("#condition_select input:checkbox:checked").map(function() {
return this.value;
}).get().join(',');
$("#submit_checkboxes").find("a").attr('href', 'index.php?condition=' + condition);
}).change();
</script>
HTML:
<div class="mutliselect" id="condition_select">
<form method="POST" action="">
<ul>
<li><input type="checkbox" id="d1" value="1"'; if(strpos($_GET['condition'],'1') !== false){ echo 'checked="checked"';} echo'/><label for="d1" class="checkbox_title">Neu</label></li>
<!-- and 6 more of these -->
Is there a way to solve this without having to create a separate GET-variable for each checkbox?
UPDATE (once more updated accrding to comments and questions updates):
Question updated, so I will update my answer to. Use explode (http://php.net/manual/en/function.explode.php), to get all values, and implode to formulate query:
$values = explode(',', $_GET['condition']);
// VALIDATE each of values to match Your type.
if (!empty($values)) {
// $values = [1, 2, 3]
foreach ($values as $key => $value) {
$values[$key] = '(condition = \''.$value.'\')';
}
// $values = ['(condition = \'1\')', '(condition = \'2\')', '(condition = \'3\')']
$query = implode(' OR ', $values);
// $query = '(condition = \'1\') OR (condition = \'2\') OR (condition = \'3\')',
$sql = $sql . ' AND ( '.$query.' )';
}
This is Your solution I think (MYSQL multiples AND: http://forums.mysql.com/read.php?10,250552). Example of explode working:
$string = '1,2,3,4,asd,fgh';
$array = explode(',', $string);
print_r($array[0]); // 1
print_r($array[3]); // 4
print_r($array[5]); // 'fgh'
This is a fragment of answer before edits, but I think it is worth to left it here:
Hoverwer, there are many security holes in it!!!
YOU MUST verify the user data. If someone pass in the address for example:
index.php?condition=; SHOW TABLES FROM database;
It can potentialy show some data. As You can see, user can also go to address with delete statemant, or INSERT INTO users... etc.
So in that case YOU SHOULD switch to PDO (for example) http://php.net/manual/en/pdo.prepare.php, and make prepared statements. Verify user data so if You need the number, he can pass only number.
You can use isset also: isset vs empty vs is_null. It is not a must, but sometimes can be useful. With each form you can also check for isset ($_POST['submit']) as many robots that spam POST forms, sometimes just ommit the submit button. It will decrease the amount of requests I think.
Remember that using POST and GET forms ALWAYS allow user to send his own POST / GET requests. In that case, server side verification is a MUST.
PS. Sorry for capital letters, they are used only to make it really STRONG. Verify user data ;).
Best regards.

Updating database according to check-boxes checked

I've the following table layout in my database with some data.
I'm taking input by check-boxes so user can select all applicable accident road conditions and it to database. I would say it is okay if you're adding a new record you just loop through the checkboexs checked and insert them in DB
The first information is now saved in the database, now user decided to change the road conditions for any reasons user came back and change it the to the following.
Now my question, how should I update my table. The first thing that came into my mind was to delete the record that were already there and insert the new one's.
My real issue here is, assume user have choose the 3 items before but changed it two or one then how would i delete the those are not checked you know what I'm saying. Below is some code snippets that I've been trying.
$accidentRoadConditions = AccidentRoadConditions::findAccidentRoadConditions($acc_det_id);
$wc_array = [];
while ($roadConditions = $accidentRoadConditions ->fetch(PDO::FETCH_OBJ)) {
$wc_array[] = $roadConditions ->rc_id;
}
Above I'm selecting all the road conditions that is already stored in the database.
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
//AccidentRoadConditions::save(array(null, $ad_lsid, $rc_id));
// $tmprory = AccidentRoadConditions::findByADAndRCIds($acc_det_id, $rc_id);
// if(!$tmprory){
// AccidentRoadConditions::save(array(null, $acc_det_id, $rc_id));
// }
if(in_array($rc_id, $wc_array)){
$errors[] = "in array <br />";
unset($wc_array[0]);
}
}
}
So my question is how to update values in database according to what was checked by user and deleting those which were unchecked which were checked before. Getting bit complicated so simply how to update database according to above mention scenario.
Any Idea?
I think you need to do the following
Store the selected checks in an array
Check in the database if any of those are already saved or not
if yes, skipped them otherwise add them into an array
$old_rc_array = [];
$new_rc_array = [];
while ($roadConditions = $accidentRoadConditions->fetch(PDO::FETCH_OBJ)) {
$old_rc_array[] = $roadConditions->rc_id;
}
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
if(in_array($rc_id, $old_rc_array)){
unset($old_rc_array[array_search($rc_id, $old_rc_array)]);
}else{
$new_rc_array[] = $rc_id;
}
}
}
foreach ($old_rc_array as $rc_to_delete) {
AccidentRoadConditions::deleteByADIdAndRCId($hidden_acc_det_id, $rc_to_delete);
}
foreach ($new_rc_array as $rc_to_insert) {
AccidentRoadConditions::save(array(null, $hidden_acc_det_id, $rc_to_insert));
}
I think this is what you should do.
Create composite unique constraint on ad_id and rc_id
Delete all the rows not in the selected checkbox ids.
Try to insert all the rows but user INSERT IGNORE. This will insert the record if it does not exist or it will just ignore it. As you are using some framework see how you can do that.
If you can not then just wrap it using try/catch and ignore if the error is related to constraint violation.
This way You don't need to check if the values exist and also there will not be any unnecessary inserts.

text input (seperated by comma) mysql input as array

I have a form where I am trying to implement a tag system.
It is just an:
<input type="text"/>
with values separated by commas.
e.g. "John,Mary,Ben,Steven,George"
(The list can be as long as the user wants it to be.)
I want to take that list and insert it into my database as an array (where users can add more tags later if they want). I suppose it doesn't have to be an array, that is just what seems will work best.
So, my question is how to take that list, turn it into an array, echo the array (values separated by commas), add more values later, and make the array searchable for other users. I know this question seems elementary, but no matter how much reading I do, I just can't seem to wrap my brain around how it all works. Once I think I have it figured out, something goes wrong. A simple example would be really appreciated. Thanks!
Here's what I got so far:
$DBCONNECT
$artisttags = $info['artisttags'];
$full_name = $info['full_name'];
$tel = $info['tel'];
$mainint = $info['maininst'];
if(isset($_POST['submit'])) {
$tags = $_POST['tags'];
if($artisttags == NULL) {
$artisttagsarray = array($full_name, $tel, $maininst);
array_push($artisttagsarray,$tags);
mysql_query("UPDATE users SET artisttags='$artisttagsarray' WHERE id='$id'");
print_r($artisttagsarray); //to see if I did it right
die();
} else {
array_push($artisttags,$tags);
mysql_query("UPDATE users SET artisttags='$artisttags' WHERE id='$id'");
echo $tags;
echo " <br/>";
echo $artisttags;
die();
}
}
Create a new table, let's call it "tags":
tags
- userid
- artisttag
Each user may have multiple rows in this table (with one different tag on each row). When querying you use a JOIN operation to combine the two tables. For example:
SELECT username, artisttag
FROM users, tags
WHERE users.userid = tags.userid
AND users.userid = 4711
This will give you all information about the user with id 4711.
Relational database systems are built for this type of work so it will not waste space and performance. In fact, this is the optimal way of doing it if you want to be able to search the tags.

Lots of 'If statement', or a redundant mysql query?

$url = mysql_real_escape_string($_POST['url']);
$shoutcast_url = mysql_real_escape_string($_POST['shoutcast_url']);
$site_name = mysql_real_escape_string($_POST['site_name']);
$site_subtitle = mysql_real_escape_string($_POST['site_subtitle']);
$email_suffix = mysql_real_escape_string($_POST['email_suffix']);
$logo_name = mysql_real_escape_string($_POST['logo_name']);
$twitter_username = mysql_real_escape_string($_POST['twitter_username']);
with all those options in a form, they are pre-filled in (by the database), however users can choose to change them, which updates the original database. Would it be better for me to update all the columns despite the chance that some of the rows have not been updated, or just do an if ($original_db_entry = $possible_new_entry) on each (which would be a query in itself)?
Thanks
I'd say it doesn't really matter either way - the size of the query you send to the server is hardly relevant here, and there is no "last updated" information for columns that would be updated unjustly, so...
By the way, what I like to do when working with such loads of data is create a temporary array.
$fields = array("url", "shoutcast_url", "site_name", "site_subtitle" , ....);
foreach ($fields as $field)
$$field = mysql_real_escape_string($_POST[$field]);
the only thing to be aware of here is that you have to be careful not to put variable names into $fields that would overwrite existing variables.
Update: Col. Shrapnel makes the correct and valid point that using variable variables is not a good practice. While I think it is perfectly acceptable to use variable variables within the scope of a function, it is indeed better not use them at all. The better way to sanitize all incoming fields and have them in a usable form would be:
$sanitized_data = array();
$fields = array("url", "shoutcast_url", "site_name", "site_subtitle" , ....);
foreach ($fields as $field)
$sanizited_data[$field] = mysql_real_escape_string($_POST[$field]);
this will leave you with an array you can work with:
$sanitized_data["url"] = ....
$sanitized_data["shoutcast_url"] = ....
Just run a single query that updates all columns:
UPDATE table SET col1='a', col2='b', col3='c' WHERE id = '5'
I would recommend that you execute the UPDATE with all column values. It'd be less costly than trying to confirm that the value is different than what's currently in the database. And that confirmation would be irrelevant anyway, because the values in the database could change instantly after you check them if someone else updates them.
If you issue an UPDATE against MySQL and the values are identical to values already in the database, the UPDATE will be a no-op. That is, MySQL reports zero rows affected.
MySQL knows not to do unnecessary work during an UPDATE.
If only one column changes, MySQL does need to do work. It only changes the columns that are different, but it still creates a new row version (assuming you're using InnoDB).
And of course there's some small amount of work necessary to actually send the UPDATE statement to the MySQL server so it can compare against the existing row. But typically this takes only hundredths of a millisecond on a modern server.
Yes, it's ok to update every field.
A simple function to produce SET statement:
function dbSet($fields) {
$set='';
foreach ($fields as $field) {
if (isset($_POST[$field])) {
$set.="`$field`='".mysql_real_escape_string($_POST[$field])."', ";
}
}
return substr($set, 0, -2);
}
and usage:
$fields = explode(" ","name surname lastname address zip fax phone");
$query = "UPDATE $table SET ".dbSet($fields)." WHERE id=$id";

Categories