I've been learning about DRY code and my code isn't DRY...
For example, I have a custom CMS and I save basically a name, content and a publish status for a few things... like an article, a user, a event. To submit a form, I submit to a file (process.php) which has a switch in it like so:
switch($_POST['process']) {
case 'speaker':
if($_POST['speaker_id']) {
$sql = '
UPDATE speakers
SET speaker_name="' . mysql_escape_string($_POST['speaker_name']) . '",
speaker_content="' . mysql_escape_string($_POST['speaker_content']) . '",
speaker_status="' . $_POST['speaker_status'] . '"
WHERE speaker_id="' . $_POST['speaker_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO speakers
SET speaker_name="' . mysql_escape_string($_POST['speaker_name']) . '",
speaker_content="' . mysql_escape_string($_POST['speaker_content']) . '",
speaker_status="' . $_POST['speaker_status'] . '"
';
}
mysql_query($sql);
if($_POST['speaker_id']) {
header('Location: speakers?speaker_id=' . $_POST['speaker_id']);
} else {
header('Location: speakers?speaker_id=' . mysql_insert_id);
}
break;
case 'event':
if($_POST['event_id']) {
$sql = '
UPDATE events
SET event_name="' . mysql_escape_string($_POST['event_name']) . '",
event_content="' . mysql_escape_string($_POST['event_content']) . '",
event_status="' . $_POST['event_status'] . '"
WHERE event_id="' . $_POST['event_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO events
SET event_name="' . mysql_escape_string($_POST['event_name']) . '",
event_content="' . mysql_escape_string($_POST['event_content']) . '",
event_status="' . $_POST['event_status'] . '"
';
}
mysql_query($sql);
if($_POST['event_id']) {
header('Location: events?event_id=' . $_POST['event_id']);
} else {
header('Location: events?event_id=' . mysql_insert_id);
}
break;
case 'article':
if($_POST['article_id']) {
$sql = '
UPDATE articles
SET article_name="' . mysql_escape_string($_POST['article_name']) . '",
article_content="' . mysql_escape_string($_POST['article_content']) . '",
article_status="' . $_POST['article_status'] . '",
article_modified="' . $_POST['article_modified'] . '"
WHERE article_id="' . $_POST['article_id'] . '"
LIMIT 1
';
} else {
$sql = '
INSERT INTO articles
SET article_name="' . mysql_escape_string($_POST['article_name']) . '",
article_content="' . mysql_escape_string($_POST['article_content']) . '",
article_status="' . $_POST['article_status'] . '"
';
}
mysql_query($sql);
if($_POST['article_id']) {
header('Location: articles?article_id=' . $_POST['article_id']);
} else {
header('Location: articles?article_id=' . mysql_insert_id);
}
break;
}
Despite some basic variations, like different table names and column names, and perhaps there sometimes being a couple more or less columns to populate, the code is literally the same and programming like this feels more like data entry than creativity.
I imagine there's a way to create a class for this so that all the below code could be achieved in 1/3 the amount. Is there some sort of streamlined mysql insert / update method/strategy?
In my head, I'm thinking if I name all my inputs the same as they are in the table, ie if the column is called 'speaker_name' and the input is..
<input type="text" name="speaker_name" />
...I wonder if I could have a function which went through the $_POST array and simply updated the appropriate fields. Is this sound logic?
Perhaps I would have a hidden input in the form which was the 'table' variable which let the function know which table to update and it takes care of the rest.
Excuse me while I just thought out-loud. Any ideas would be really cool!
My newbie solution
Here's what I have i got working
if($_POST['id']) {
$sql = 'UPDATE ';
} else {
$sql = 'INSERT INTO ';
}
// number of rows in array
$total = count($_POST);
// number of commas = total of values minus 1
$commas = $total - 1;
// starting number
$count = 1;
foreach ($_POST as $key => $value) {
if($count == 1)
{
$sql .= mysql_real_escape_string($value) . ' SET ';
}
else
{
if( $count < $total )
{
$sql .= $key . '="' . mysql_real_escape_string($value) . '"';
if($count != $commas)
{
$sql .= ', ';
}
}
elseif( $_POST['id'] )
{
$sql .= ' WHERE ' . $key . '="' . mysql_real_escape_string($value) . '"';
}
}
$count = $count + 1;
}
mysql_query($sql);
if($_POST['id']) {
header('Location: ' . $_POST['process'] . '?id=' . $_POST['id'] . '');
} else {
header('Location: ' . $_POST['process'] . '?id=' . mysql_insert_id());
}
To do this means my form designs need to have a pretty strict setup ie the first hidden input holds the table name, the last input is the id number of the row in the table being edited (if it exists).
I know its far from good... but a lot better than the hundreds of lines it previously took.
1) some flaws in your concept
every piece of data you're going to put into quotes in your query, should be processed with
mysql_real_escape_string, as you cannot know what can be inside.
never use a table name passed from the client side. there can be malicious code instead of mere table name as well.
same for the field names. every identifier should be hardcoded in your script.
2) as for the DRY - it's simple. just note similar parts in your code and put them into function. only fields differ? okay, make a function that take fields list and produce an SQL statement of them.
Luckily, Mysql let us use similar syntax for both insert and update. So, a very simple function like this one can help:
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);
}
So, you can make your code shorter:
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
if(isset($_POST['speaker_id'])) {
$id = intval($_POST['speaker_id']);
$query = "UPDATE $table SET ".dbSet($fields)." WHERE id=$id";
} else {
$query = "INSERT INTO $table SET ".dbSet($fields);
}
mysql_query($sql) or trigger_error(mysql_error().$query);
if($_POST['speaker_id']) $id = mysql_insert_id();
header('Location: speakers?speaker_id='.$id);
break;
if all your actions are such alike, you can make more high leveled functions:
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
if(isset($_POST['speaker_id'])) {
$id = intval($_POST['speaker_id']);
dbUpdate($table,$fields,$id);
} else {
$id = dbInsert($table,$fields);
}
header('Location: speakers?speaker_id='.$id);
exit;
break;
and even more high level
case 'speaker':
$table = "speakers";
$fields = explode(" ","speaker_name speaker_content speaker_status");
$id = dbMagic();
header('Location: speakers?speaker_id='.$id);
exit;
break;
But I won't go into that. I'd stop at 1st option, because it's pretty straightforward and there are always some little things not fit into such a broad concept.
While your alignment of column names and perhaps a hidden form field for table name would be quicker to code and more elegant to code against you would be opening yourself up to someone spoofing an HTML file to control the inserts to a table! Consider refactoring in other ways to optimize your library. Keep thinking / you're bound to come up with a better solution within the context of your problem domain.
Usually, one has some base models to do this, for example (don't be to harsh about it's failtings, I just want to give a short example):
class Speaker {
function __construct($data){
foreach($data as $key => $value) $this->$key = $value;
}
function save(){
$query =
($this->speaker_id ? 'UPDATE ':'INSERT INTO').' speakers '
."SET speaker_name='%s',
speaker_content='%s',
speaker_status='%s'"
.($this->speaker_id ? ' WHERE speaker_id=%d ':'');
mysql_query(sprintf($query(
mysql_real_escape_string($this->speaker_name),
mysql_real_escape_string($this->speaker_content),
mysql_real_escape_string($this->speaker_status),
intval($this->speaker_id)));
if(!$this->speaker_id) $this->speaker_id = mysql_insert_id();
}
}
And then:
switch($_POST['process']) {
case 'speaker':
$speaker = new Speaker($_POST);
$speaker->save();
header('Location: /speakers?speaker_id='.$speaker->speaker_id);
But for new projects, I would suggest a more complete MVC pattern (where Event & Speaker can be subclasses from some base databasemodel, possibly able to generate some form based on settings), and use prepared statements, they will make your sql queries easier & safer. never use addslashes, for good ol' mysql_query use mysql_real_escape_string
Related
I am quite new in php and trying to write my first scripts. I put values in a database. If a record has to be changed, the user can choose the id of the record that has to be changed. Some datas will remain, only read and some f.e. remarks can be changed. I have no problem with getting the datas from the database, but with storing the changed values.
User can choose the record to be changed:
public function bejelentesKivalasztas(){
$this->kapcsolodas();
$sqlHibabejelentesekTablabol = "SELECT bejelentesID FROM hibarogzites";
$this->hibabejelentesekTablabol = mysqli_query($this->kapcs, $sqlHibabejelentesekTablabol);
$sorokSzama = mysqli_num_rows($this->hibabejelentesekTablabol);
global $adat;
global $i;
$adat = [];
print("<select class='textarea' name='bejelentes_ID' id='bejelentes_ID' style='width: 220px'>");
for ($i=0; $i<$sorokSzama; $i++){
$adat[$i] = mysqli_fetch_array($this->hibabejelentesekTablabol);
print("<option value='" . $adat[$i]['bejelentesID'] . "'> " . $adat[$i]['bejelentesID'] . " </option>");
}
}
Necessary datas will be recalled and printed with the possibility to change some of them:
<?php
if(isset($_POST['bejelentesKivalasztas'])){
$bejelentesID = $_POST['bejelentes_ID'];
$boltCimBeolvasas = new adatlekerdezes($bejelentesID);
$boltCimBeolvasas ->boltCimBeolvasas($bejelentesID);
}
?>
public function boltCimBeolvasas(){
if(isset($_POST['bejelentesKivalasztas'])){
$bejelentesID = $_POST['bejelentes_ID'];
$this->kapcsolodas();
global $boltSzam, $boltVaros, $boltIrsz, $boltUtca, $bejelentesID;
$this->bejelentesID = $bejelentesID;
$this->egyBoltkivalasztas();
$sqlReadBoltAddressFromTable= "SELECT * FROM boltok WHERE boltID = '" . $this->boltID ."'";
$boltCimBeolvasas = mysqli_query($this->kapcs,$sqlReadBoltAddressFromTable);
$this->adat2 = mysqli_fetch_array($boltCimBeolvasas);
$this->boltSzam = $this->adat2[1];
$boltSzam = $this->boltSzam;
$boltIrsz = $this->adat2[2];
$boltVaros = $this->adat2[3];
$boltUtca = $this->adat2[4];
$this->bejelentesLehivas($this->bejelentesID);
$this->megjegyzesBeolvasas($this->bejelentesID);
}
}
public function megjegyzesBeolvasas(){
$this->kapcsolodas();
global $bejelMegjegyz;
$hibabejelentesekTablabol = [];
$this->sqlHibabejelentesekTablabol = "SELECT megjegyzesSzoveg FROM hibarogzites where bejelentesID = '" . $this->bejelentesID . "'";
$hibabejelentesekTablabol = mysqli_fetch_array(mysqli_query($this->kapcs, $this->sqlHibabejelentesekTablabol));
global $adat3;
$adat3 = [];
$this->adat3 = $hibabejelentesekTablabol;
$bejelMegjegyz = $this->adat3[0];
return $bejelMegjegyz;
}
But when restoring should follow, the ID (bejelentesID) gets lost and as this, data will not change.
public function bejelentesMod($intezkedes, $megjegyzes, $szerelo, $bejelentesID){
$this->kapcsolodas();
$sqlSzereloAdat = "SELECT *
FROM szerelo
WHERE szerelo_nev = '" . $szerelo . "'";
$szereloAdat = mysqli_fetch_array(mysqli_query($this->kapcs, $sqlSzereloAdat));
print("Szerelőadat: " . $szereloAdat['szereloID'] . " eddig / ");
$this->szereloID = $szereloAdat['szereloID'];
$this->intezkedesID = $intezkedes;
$this->bejelentesID = $bejelentesID;
print("intID: " . $this->intezkedesID);
print(" / bejelID: " . $this->bejelentesID);
$sqlHibabejelentesFrissites = "UPDATE hibarogzites SET megjegyzesSzoveg = '" . $megjegyzes . "', intezkedesID = '" . $this->intezkedesID . "', szereloID = '" . $this->szereloID . "', felhasznaloID = '" . $this->felhasznaloID . "' WHERE bejelentesID = '" . $this->bejelentesID . "'";
$hibabejelentesFrissites = mysqli_query($this->kapcs, $sqlHibabejelentesFrissites);
print(', $sqlhibabejelentesFrissítés értéke: ' . $sqlHibabejelentesFrissites);
if(!mysqli_connect_errno()){
$this->message = "A bejegyzés módosítva";
}
else{
$this->message = "A bejegyzés módosítása nem sikerült";
}
// header('Location: hibabejelentesek.php');
}
From that point that the id gets lost, the update cannot happen. I tried the mysql command at it worked in the sql programm directly. I inserted the
print("intID: " . $this->intezkedesID);
print(" / bejelID: " . $this->bejelentesID);
in function bejelentesMod to see what was the problem.
Maybe session can be the solution - but the id must be changed when another record must be changed. Can I use this session variable despite of that?
I suppose there are several problems with this code, but as I wrote - this is my first one. Even though I hope someone can me help how to get it work.
Thanks in advance for any help.
I have a function that uses mysqli function that is as follows:
public function GetProjectOptions()
{
$return = "";
$sql = "SELECT `id`, `project_name` FROM `projects`;";
$rs = static::$link->query($sql);
$return .= '<select class="form-control" name="project">';
while ($result = mysqli_fetch_assoc($rs));
{
$return .= "<option value='" . $result['id'] . "'>" .
$result['project_name'] . "</option>";
}
$return .= '</select>';
return $return;
}
The purpose of this function is to create the options and select that will be used for the Projects on my site, I know that there are 4 projects currently stored in the table, but they do not return in this function, what have I done wrong?
EDIT:
Link to screen output: (http://i.imgur.com/YIYiheH.png)
Link to code output: (http://i.imgur.com/RZsUIwQ.png)
Link to code usage: (http://i.imgur.com/4J9rvd7.png)
(Wouldn't let me do normal links)
I found the problem.
Remove the semi-colon here
while ($result = mysqli_fetch_assoc($rs));
^
that's why it's not throwing an error, because it's considered as valid syntax.
Your loop is being stopped/terminated by it.
What I think Jay and Styphon mean by their comment is that you don't do any error checking within your SELECT query. Are you sure your query is executing properly? I understand this is a relatively simple query and that you're positive there are four projects currently stored in your table, but it's always a good habit to check. Try this:
public function GetProjectOptions()
{
$return = "";
$sql = "SELECT `id`, `project_name` FROM `projects`;";
$rs = static::$link->query($sql);
$return .= '<select class="form-control" name="project">';
if($rs){
while ($result = mysqli_fetch_assoc($rs));
{
$return .= "<option value='" . $result['id'] . "'>" . $result['project_name'] . "</option>";
}
$return .= '</select>';
}else{
$message = 'Invalid query: ' . mysqli_error() . "\n";
$message .= 'Whole query: ' . $sql;
die($message);
}
return $return;
}
I hope this helps!
I looked through the stack questions and answers, but didn't see anything I could directly apply here. Maybe I'm just missing something.
The code below works fine, except when I include my where statement which refers to the value of the $wp_user_id variable.
I've checked that the variable IS actually being populated with a $user_id when the script is loaded. It appears that the value of this variable is lost right after the call to the conManager function, but I don't understand why. There doesn't appear to be anything within the ConnectionManager.php file (which defines the conManager function) which would touch this variable, so I'm at a loss.
I'm a PHP hack, so go easy on me, but what is causing me to lose the value of my variable, and how do I address it? Here's the code:
<?php
include_once("/home/evaluate/public_html/admin/php/ConnectionManager.php");
header('Content-type:text/javascript;charset=UTF-8');
$wp_user_id = $_GET["user"];
$json1=json_decode(stripslashes($_POST["_gt_json"]));
$pageNo = $json1->{'pageInfo'}->{'pageNum'};
$pageSize = $json1->{'pageInfo'}->{'pageSize'};
if(isset($json1->{'sortInfo'}[0]->{'columnId'})){
$sortField = $json1->{'sortInfo'}[0]->{'columnId'};
}
else{
$sortField = "miles_on_oil";
}
if(isset($json1->{'sortInfo'}[0]->{'sortOrder'})){
$sortOrder = $json1->{'sortInfo'}[0]->{'sortOrder'};
}
else{
$sortOrder = "ASC";
}
if($json1->{'sortInfo'}[0]->{'sortOrder'} == "defaultsort"){
$sortField = "miles_on_oil";
$sortOrder = "ASC";
}
if($json1->{'filterInfo'}[0]->{'value'} != "") {
for ($i = 0; $i < count($json1->{'filterInfo'}); $i++) {
if($json1->{'filterInfo'}[$i]->{'logic'} == "equal"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . "='" . $json1->{'filterInfo'}[$i]->{'value'} . "' ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "notEqual"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . "!='" . $json1->{'filterInfo'}[$i]->{'value'} . "' ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "less"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . "<" . $json1->{'filterInfo'}[$i]->{'value'} . " ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "lessEqual"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . "<=" . $json1->{'filterInfo'}[$i]->{'value'} . " ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "great"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . ">" . $json1->{'filterInfo'}[$i]->{'value'} . " ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "greatEqual"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . ">=" . $json1->{'filterInfo'}[$i]->{'value'} . " ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "like"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . " LIKE '%" . $json1->{'filterInfo'}[$i]->{'value'} . "%' ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "startWith"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . " LIKE '" . $json1->{'filterInfo'}[$i]->{'value'} . "%' ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == "endWith"){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . " LIKE '%" . $json1->{'filterInfo'}[$i]->{'value'} . "' ";
}elseif($json1->{'filterInfo'}[$i]->{'logic'} == ""){
$filter .= $json1->{'filterInfo'}[$i]->{'columnId'} . " LIKE '%" . $json1->{'filterInfo'}[$i]->{'value'} . "' ";
}
$filter .= " AND ";
}
}
else {
$filter = '';
}
//print_r ($json1);
//die;
// Temp TEsting Values
// End Temp Testing Values
$conManager = new ConManager();
$conManager->getConnection();
if($json1->{'action'} == 'load'){
//to get how many records totally.
$sql = "select count(*) as cnt from oil_analysis_data where $filter user_id = '".$wp_user_id."'";
$handle = mysql_query($sql);
$row = mysql_fetch_object($handle);
$totalRec = $row->cnt;
$sql2 = "select * from oil_analysis_data where $filter user_id = '".$wp_user_id."' ORDER BY " . $sortField . " " . $sortOrder . " limit " . ($pageNo - 1)*$pageSize . ", " . $pageSize;
$handle2 = mysql_query($sql2);
$retArray2 = array();
while($row2 = mysql_fetch_assoc($handle2)) {
// Grab Vehicle Make, Model & Year "Names" from their respective tables & insert into the array
$year = "select Name from vehicle_data_years where ID = {$row2['list1']}";
$year1 = mysql_query($year);
$year2 = mysql_fetch_assoc($year1);
$year3 = $year2['Name'];
$make = "select Name from vehicle_data_makes where ID = {$row2['list2']}";
$make1 = mysql_query($make);
$make2 = mysql_fetch_assoc($make1);
$make3 = $make2['Name'];
$model = "select Name from vehicle_data_all where ID = {$row2['list3']}";
$model1 = mysql_query($model);
$model2 = mysql_fetch_assoc($model1);
$model3 = $model2['Name'];
$row2['list1'] = $year3;
$row2['list2'] = $make3;
$row2['list3'] = $model3;
// Grab Motor oil Viscosity, Brand & Product "Names" from their respective tables & insert into the array
$visc = "select name from viscosity where id = {$row2['viscosity']}";
$visc1 = mysql_query($visc);
$visc2 = mysql_fetch_assoc($visc1);
$visc3 = $visc2['name'];
$brand = "select brandname from oil_brand where brandid = {$row2['brand']}";
$brand1 = mysql_query($brand);
$brand2 = mysql_fetch_assoc($brand1);
$brand3 = $brand2['brandname'];
$product = "select product_name from oil_data where id = {$row2['product']}";
$product1 = mysql_query($product);
$product2 = mysql_fetch_assoc($product1);
$product3 = $product2['product_name'];
$row2['viscosity'] = $visc3;
$row2['brand'] = $brand3;
$row2['product'] = $product3;
if($row2['bypass_filtration'] == 1) {
$row2['bypass_filtration'] = "<img src='http://themotoroilevaluator.com/admin/php/crud/images/checkmark.png' style='border: 0px;'>";
}
else {$row2['bypass_filtration'] = "";
}
if($row2['oil_change'] == 1) {
$row2['oil_change'] = "<img src='http://themotoroilevaluator.com/admin/php/crud/images/checkmark.png' style='border: 0px;'>";
}
else {$row2['oil_change'] = "";
}
$retArray[] = $row2;
}
$analysis_data = json_encode($retArray);
$ret = "{data:" . $analysis_data .",\n";
$ret .= "pageInfo:{totalRowNum:" . $totalRec . "},\n";
$ret .= "recordType : 'object'}";
echo $ret;
}
?>
I'm curious, why do you add a semi colon after the $wp_user_id; ? I've noticed you doing this in more than one place. This may be the culprit.
$filter user_id = '".$wp_user_id;."'";
Nevermind. It would appear that my problem actually resulted from a change in my code that I had forgotten about. I changed $_REQUEST['user'] to $_GET['user'], thinking that, in this case, since the value was being passed as a URL query string, that wouldn't be a problem.
To be honest, I'm still not entirely sure why that made a difference - although I can research that on my own. But, at any rate, changing that back corrected my problem entirely.
Thanks to those who responded, though. Even if not solutions to my actual problem, the information from both turned out to be very useful.
Any hacker can severely screw up or delete your database because of the way you use direct user provided data to build up your SQL query. Please instead read up on SQL Injection, and the use of PHP prepared statements.
Relevant
i am seeking help on ignoring null values for updating the mysql database:-
$cst = $_POST['custname'];
$a = $_POST['tel'];
$b = $_POST['fax'];
$c = $_POST['email'];
$sql = mysql_query("UPDATE contacts SET TEL = '$a', FAX = '$b', EMAIL = '$c'
WHERE Cust_Name = '$cst' ");
how do i incorporate an option where the user can only select one or all fields for updation.
i tried using the following code based on responses received but it does the same thing. overwrites the existing data with the blank ones.
$upd = mysql_query("UPDATE custcomm_T SET
Telephone = ".(is_null($a)?'Telephone':"'$a'").",
Fax = ".(is_null($b)?'Fax':"'$b'").",
Mobile = ".(is_null($c)?'Mobile':"'$c'").",
EMail = ".(is_null($d)?'EMail':"'$d'").",
trlicense = ".(is_null($e)?'trlicense':"'$e'").",
trlicexp = ".(is_null($f)?'trlicexp':"'$f'")."
WHERE Cust_Name_VC = '$g' ") or die(mysql_error());
Firstly remember to escape any strings coming to you via POST, GET, or REQUEST (read up on SQL injection attacks if you're unsure why).
Something like this might work:
$semaphore = false;
$query = "UPDATE contacts SET ";
$fields = array('tel','fax','email');
foreach ($fields as $field) {
if (isset($_POST[$field]) and !empty($_POST[$field]) {
$var = mysql_real_escape_string($_POST[$field]);
$query .= uppercase($field) . " = '$var'";
$semaphore = true;
}
}
if ($semaphore) {
$query .= " WHERE Cust_Name = '$cst'";
mysql_query($query);
}
NB: Do not ever simply loop through your $_POST array to create a SQL statement. An opponent can add extra POST fields and possibly cause mischief. Looping through a user input array can also lead to an injection vector: the field names need to be added to the statement, meaning they're a potential vector. Standard injection prevention techniques (prepared statement parameters, driver-provided quoting functions) won't work for identifiers. Instead, use a whitelist of fields to set, and loop over the whitelist or pass the input array through the whitelist.
You need to build your query. Something like this:
$query = 'update contacts set ';
if ($_POST['tel'] != '') $query .= 'TEL="'.$_POST['tel'].'", ';
if ($_POST['fax'] != '') $query .= 'FAX="'.$_POST['fax'].'", ';
if ($_POST['email'] != '') $query .= 'EMAIL="'.$_POST['email'].'", ';
$query .= "Cust_Name = '$cst' where Cust_Name = '$cst'";
The last update field: Cust_Name = '$cst' basically is to 'remove' the last comma.
Keeping in mind that $_POST values should be cleaned before use, and that all $_POST values are strings, so an empty field is '' and not null, something like this will work:
foreach ($_POST as $var=>$value) {
if(empty($value)) continue; //skip blank fields (may be problematic if you're trying to update a field to be empty)
$sets[]="$var= '$value";
}
$set=implode(', ',$sets);
$q_save="UPDATE mytable SET $set WHERE blah=$foo";
This should work (the MySQL way):
"UPDATE `custcomm_T`
SET `Telephone` = IF(TRIM('" . mysql_real_escape_string($a) . "') != '', '" . mysql_real_escape_string($a) . "', `Telephone`),
SET `Fax` = IF(TRIM('" . mysql_real_escape_string($b) . "') != '', '" . mysql_real_escape_string($b) . "', `Fax`),
SET `Mobile` = IF(TRIM('" . mysql_real_escape_string($c) . "') != '', '" . mysql_real_escape_string($c) . "', `Mobile`),
SET `EMail` = IF(TRIM('" . mysql_real_escape_string($d) . "') != '', '" . mysql_real_escape_string($d) . "', `EMail`),
SET `trlicense` = IF(TRIM('" . mysql_real_escape_string($e) . "') != '', '" . mysql_real_escape_string($e) . "', `trilicense`),
SET `trlicexp` = IF(TRIM('" . mysql_real_escape_string($f) . "') != '', '" . mysql_real_escape_string($f) . "', `trlicexp`)
WHERE Cust_Name_VC = '" . mysql_real_escape_string($g) . '";
I've tried to keep the columns and variables to what you have posted in your question, but feel free to correct as per your schema.
Hope it helps.
Loop over the optional input fields, building up which fields to set. The field names and values should be kept separate so you can use a prepared statement. You can also loop over required fields as a basic validation step.
# arrays of input => db field names. If both are the same, no index is required.
$optional = array('tel' => 'telephone', 'fax', 'email');
$required = array('custname' => 'cust_name');
# $input is used rather than $_POST directly, so the code can easily be adapted to
# work with any array.
$input =& $_POST;
/* Basic validation: check that required fields are non-empty. More than is
necessary for the example problem, but this will work more generally for an
arbitrary number of required fields. In production code, validation should be
handled by a separate method/class/module.
*/
foreach ($required as $key => $field) {
# allows for input name to be different from column name, or not
if (is_int($key)) {
$key = $field;
}
if (empty($input[$key])) {
# error: input field is required
$errors[$key] = "empty";
}
}
if ($errors) {
# present errors to user.
...
} else {
# Build the statement and argument array.
$toSet = array();
$args = array();
foreach ($optional as $key => $field) {
# allows for input name to be different from column name, or not
if (is_int($key)) {
$key = $field;
}
if (! empty($input[$key])) {
$toSet[] = "$key = ?";
$args[] = $input[$key];
}
}
if ($toSet) {
$updateContactsStmt = "UPDATE contacts SET " . join(', ', $toSet) . " WHERE cust_name = ?";
$args[] = $input['custname'];
try {
$updateContacts = $db->prepare($updateContactsStmt);
if (! $updateContacts->execute($args)) {
# update failed
...
}
} catch (PDOException $exc) {
# DB error. Don't reveal exact error message to non-admins.
...
}
} else {
# error: no fields to update. Inform user.
...
}
}
This should be handled in a data access layer designed to map between the database and program objects. If you're clever, you can write a single method that will work for arbitrary models (related forms, tables and classes).
mysql_query("
UPDATE contacts
SET
TEL = ".(is_null($a)?'TEL':"'$a'").",
FAX = ".(is_null($b)?'FAX':"'$b'").",
EMAIL = ".(is_null($c)?'EMAIL':"'$c'")."
WHERE Cust_Name = '$cst'
");
I've got a serious issue here. I'm developing a forum, and trying to get an "unread posts" feature ready. However, for some reason my code decides to loop & get ridiculous CPU usage over my dedi. All i see from my MySQL process list is that the same sql is constantly looping.
This is my code:
public function __construct()
{
$this->getUnread();
}
private function getUnread()
{
global $cms;
// check unread threads
$forumSQL = $cms->db->query('SELECT * FROM forum_for');
while($forums = $forumSQL->fetch_assoc())
{
$forumId = $forums['id'];
$forumArray[$forumId] = $forums;
}
if($unreadThreadsSql = $cms->db->query('SELECT * FROM forum_threads WHERE posted > "' . $_SESSION['lastVisit'] . '"'))
{
while(!$unreadThreads = $unreadThreadsSql->fetch_assoc())
{
$forumId = $unreadThreads['forId'];
if($this->checkUnread($unreadThreads['id']))
{
$cms->db->query('
INSERT INTO
forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime)
VALUES(
'.$unreadThreads['id'].',
'.$forumArray[$forumId]['cat_id'].',
'.$forumId.',
'.$_SESSION['userId'].',
NOW(),
"'.$unreadThreads['posted'].'" )');
}
}
}
// check unread posts
if($unreadPostsSql = $cms->db->query('SELECT * FROM forum_posts WHERE datetime > "' . $_SESSION['lastVisit'] . '"'))
{
while($unreadPosts = $unreadPostsSql->fetch_assoc())
{
$threadSql = $cms->db->query('SELECT * FROM forum_threads WHERE id = ' . $unreadPosts['threadId']);
$thread = $threadSql->fetch_assoc();
$forumId = $thread['forId'];
if(!$this->checkUnread($thread['id']))
{
$cms->db->query('
INSERT INTO
forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime)
VALUES(
'.$thread['id'].',
'.$forumArray[$forumId]['cat_id'].',
'.$forumId.',
'.$_SESSION['userId'].',
NOW(),
"'.$thread['posted'].'" )');
}
}
}
}
private function checkUnread($id)
{
global $cms;
if($unreadSql = $cms->db->query('SELECT * FROM forum_unread WHERE threadID = ' .$id . ' AND userID = ' . $_SESSION['userId']))
{
if($unreadSql->num_rows == 1)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
Could really use some help here. I really can't find why it's looping, does anyone have an idea...
For whose wondering, it seems the code is looping in the function checkUnread().
As an extra note, when commenting the $this->getUnread(); in the constructor the entire thing stops overloading. So i'm certain it's in this bit of code.
Did you mean while($unreadThreads = $unreadThreadsSql->fetch_assoc())?
BTW it would be highly more efficient if you composed one big INSERT query then executed it once, rather than all of these little bitty queries.
Example:
$inserts = Array();
$unreadThreadsSql = $cms->db->query('SELECT * FROM forum_threads WHERE posted > "' . $_SESSION['lastVisit'] . '"') or die($cms->db->error);
while ($unreadThreads = $unreadThreadsSql->fetch_assoc()) {
$forumId = $unreadThreads['forId'];
if (!$this->checkUnread($unreadThreads['id']))
continue;
$inserts[] = '(' .
$unreadThreads['id'] . ',' .
$forumArray[$forumId]['cat_id'] . ',' .
$forumId . ',' .
$_SESSION['userId'] . ',' .
'NOW(),' .
'"' . $unreadThreads['posted'] . '")'
);
}
if (count($inserts)) {
$cms->db->query('INSERT INTO forum_unread(
threadID,
catID,
forumID,
userID,
datetime,
threadtime) VALUES' .
implode(',', $inserts)) or die($cms->db->error);
}