PHP Data Object insert not executing - php

My PHP form I just changed to use PDO. The only thing I can tell is the execute is not working. Am I supposed to pass something with it?
$db = new PDO('mysql:host=localhost;dbname=x;charset=utf8', 'x', 'x');
if ( !$db )
{
die('Could not connect: ' . mysql_error());
}
$ipaddress = $_SERVER['REMOTE_ADDR'];
$mail = $_POST['mail'];
$stmt = $db->prepare("SELECT * FROM ucm_signup WHERE email =? ");
$stmt->bindValue(1, $mail, PDO::PARAM_STR);
$stmt->execute();
if($stmt->rowCount()== 0) {
//if there are no duplicates...insert
$sql = $db->prepare("INSERT INTO ucm_signup (company, address1, address2, city, province, zip, fname, lname, email, phone, session, iama, buyfrom, group1, ipaddress)
VALUES (:company, :address1, :address2, :city, :province, :zip, :fname, :lname, :mail, :phone, :session, :iama, :buyfrom, :group1, :ipaddress)");
$sql->bindParam(":company", $_POST['company'],PDO::PARAM_STR);
$sql->bindParam(":address1", $_POST['address1'],PDO::PARAM_STR);
$sql->bindParam(":city", $_POST['city'],PDO::PARAM_STR);
$sql->bindParam(":province", $_POST['province'],PDO::PARAM_STR);
$sql->bindParam(":zip", $_POST['zip'],PDO::PARAM_STR);
$sql->bindParam(":fname", $_POST['fname'],PDO::PARAM_STR);
$sql->bindParam(":lname", $_POST['lname'],PDO::PARAM_STR);
$sql->bindParam(":email", $_POST['email'],PDO::PARAM_STR);
$sql->bindParam(":phone", $_POST['phone'],PDO::PARAM_STR);
$sql->bindParam(":session", $_POST['session'],PDO::PARAM_STR);
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR);
$sql->bindParam(":buyfrom", $_POST['buyfrom'],PDO::PARAM_STR);
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR);
$sql->bindParam(":group1", $_POST['group1'],PDO::PARAM_STR);
$sql->bindParam(":ipaddress", $_POST['ipaddress'],PDO::PARAM_STR);
$sql->execute();
}
My database table has no records. Thank you

You are missing some placeholder in your bind parameters, check them carefully
$sql->bindParam(":address1", $_POST['address1'],PDO::PARAM_STR);
$sql->bindParam(":address2", $_POST['city'],PDO::PARAM_STR);
//address2 was missed, probably error is column doesn't match values
$sql->bindParam(":email", $_POST['email'],PDO::PARAM_STR); //supposed to be mail
$sql->bindParam(":imea", $_POST['imea'],PDO::PARAM_STR); //supposed to be iama
You might want to check for pdo errors, here an example taken from manual
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
With this attribute correctly added pdo will notify you if any error occur

PHP users are so PHP users.
First they're laboring on a WALL of code, consists of constantly repeating nearly hundred variables.
Then they get totally lost.
While everything can be done with short and concise code, writing each field name only ONCE
$allowed = array('company', 'address1', 'address2', 'city', 'province',
'zip', 'fname', 'lname', 'email', 'phone', 'session',
'iama', 'buyfrom', 'group1', 'ipaddress');
$_POST['ipaddress'] = $_SERVER['REMOTE_ADDR'];
$sql = "INSERT INTO ucm_signup SET ".pdoSet($allowed, $values);
$stm = $dbh->prepare($sql);
$stm->execute($values);
where pdoSet() helper function can be stored elsewhere and reused for the every insert or update query
function pdoSet($fields, &$values, $source = array()) {
$set = '';
$values = array();
if (!$source) $source = &$_POST;
foreach ($fields as $field) {
if (isset($source[$field])) {
$set.="`".str_replace("`","``",$field)."`". "=:$field, ";
$values[$field] = $source[$field];
}
}
return substr($set, 0, -2);
}

Related

PHP/MySQL INSERT same data INTO two Tables

I have two forms that share some same columns: NAME, EMAIL, NOMINEE, DEPT, RANK and TIMESTAMP
and I want to store those same columns in a new table called: TEACHING_AWARD_ALL_NOMINATIONS.
I have came up with the code to store each data into different table and then there should be some code to store the shared columns into TEACHING_AWARD_ALL_NOMINATIONS table.
I haven't came up with the code yet, please help!!!!
$srr = array_map('mysql_escape_string', $_REQUEST);
if ($srr['NOMINATIONTYPE'] == 'STUDENT')
$fields = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'COURSE', 'YEARTERM', 'REQUIRED_FOR_MAJOR', 'MAJOR_LEARNING_OBJECTIVES', 'WHAT_EXTENT_INSTRUCTOR_HELP', 'RANK', 'RANK_COMMENT', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3', 'TEXTBOX_4', 'TEXTBOX_5');
else if ($srr['NOMINATIONTYPE'] == 'FACULTY')
$fields = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'RANK', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3');
else die('error: no nomination type');
foreach ($fields as $f)
$$f = $srr[$f];
$qry = "INSERT INTO TEACHING_AWARD_".$srr['NOMINATIONTYPE']."_NOMINATIONS (";
foreach ($fields as $f) $qry .= $f . ", ";
$qry = substr($qry, 0, -2);
$qry .= ") VALUES (";
foreach ($fields as $f) $qry .= "'" . $$f . "', ";
$qry = substr($qry, 0, -2);
$qry .= ")";
$result = mysql_query($qry) or die('An error ocurred: '.mysql_error());
echo 'Success! Thank you for submitting your nomination.';
WARNING! As noted in comments your original code is using deprecated functions and suffers from potential security issues.
Check out the refactored solution that is using PDO, and yes you
should use PDO too (instead of your current approach).
Check out the code below, untested but should do your job. As written above it uses PDO - check the docs here
// obviously, first set your connection parameters $DbHost, $DbName etc.
//connect to mysql
$dbh = new PDO("mysql:host=".$DbHost.";dbname=".$DbName, $DbUser, $DbPass, array(PDO::ATTR_PERSISTENT => true));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->query('SET NAMES UTF8'); //assuming you use utf-8 encoding
//provide values array
$values = $YourValuesArray;
//set field types
$fields = array();
$fieldsStudent = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'COURSE', 'YEARTERM', 'REQUIRED_FOR_MAJOR', 'MAJOR_LEARNING_OBJECTIVES', 'WHAT_EXTENT_INSTRUCTOR_HELP', 'RANK', 'RANK_COMMENT', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3', 'TEXTBOX_4', 'TEXTBOX_5');
$fieldsFaculty = Array('NAME', 'EMAIL', 'NOMINEE', 'DEPT', 'RANK', 'TEXTBOX_1', 'TEXTBOX_2', 'TEXTBOX_3');
$fieldsAll = array_intersect($fieldsStudent, $fieldsFaculty);
//pick the proper field set or die
$fields = ($srr['NOMINATIONTYPE'] == 'STUDENT') ? $fieldsStudent : $fieldsFaculty;
if(empty($fields)) die('error: no nomination type');
//set tables
$table = 'TEACHING_AWARD_'.$srr['NOMINATIONTYPE'].'_NOMINATIONS';
$tableAll = 'TEACHING_AWARD_ALL_NOMINATIONS';
//construct fields string
$strFields = implode(",", $fields);
$strFieldsAll = implode(",", $fieldsAll);
//construct the placeholders string
$strIns = implode(",", array_map(function($item){ return ":".$item; }, $fields));
$strInsAll = implode(",", array_map(function($item){ return ":".$item; }, $fieldsAll));
//insert specific data
$sql = "INSERT INTO $table ($strFields) VALUES ($strIns)";
$sth = $dbh->prepare($sql);
//bind values to placeholders
foreach ($fields as $f)
{
$sth->bindValue(':' . $f, $values[$f]);
}
$sth->execute();
//insert all data
$sql = "INSERT INTO $tableAll ($strFieldsAll) VALUES ($strInsAll)";
$sth = $dbh->prepare($sql);
//bind values to placeholders
foreach ($fieldsAll as $f)
{
$sth->bindValue(':' . $f, $values[$f]);
}
$sth->execute();
EDIT:
As per your comment, to select a UNIONed set of results using PDO you can use the below (untested) code:
//connect to mysql
$dbh = new PDO("mysql:host=".$DbHost.";dbname=".$DbName, $DbUser, $DbPass, array(PDO::ATTR_PERSISTENT => true));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->query('SET NAMES UTF8'); //assuming you use utf-8 encoding
$sql = "SELECT NAME, EMAIL, NOMINEE, DEPT, RANK, TIMESTAMP, 'STUDENT' AS TYPE FROM TEACHING_AWARD_STUDENT_NOMINATIONS
UNION
SELECT NAME, EMAIL, NOMINEE, DEPT, RANK, TIMESTAMP, 'FACULTY' AS TYPE FROM TEACHING_AWARD_FACULTY_NOMINATIONS";
$sth = $dbh->prepare($sql);
$sth->execute();
//init result array
$results = array();
//fetch the results into an array
while($row = $sth->fetch(PDO::FETCH_ASSOC))
$results[] = $row;
//show results or do whatever else you need
print_r($results);
You could try making two arrays, one for the "shared" columns (NAME, EMAIL, etc.) and another for the "type-specific" columns (COURSE, YEARTERM, etc.). Then, when you are building up your SQL statement, do a foreach on the "shared" columns followed immediately by the "type-specific" columns to simulate the entire table. It might look something like this:
$qry = "INSERT INTO TEACHING_AWARD_".$srr['NOMINATIONTYPE']."_NOMINATIONS (";
foreach ($fields_shared as $f) $qry .= $f . ", ";
foreach ($fields_typespecific as $f) $qry .= $f . ", ";
$qry = substr($qry, 0, -2);
$qry .= ") VALUES (";
foreach ($fields_shared as $f) $qry .= "'" . $$f . "', ";
foreach ($fields_typespecific as $f) $qry .= "'" . $$f . "', ";
$qry = substr($qry, 0, -2);
$qry .= ")";
I would also agree with th3falc0n's comment about looking into preparing your SQL statements with more robust tools.
Another consideration: rather than enter redundant data into a TEACHING_AWARD_ALL_NOMINATIONS table, why not simply make that a view that pulls all shared columns from each type-specific table (likely using a UNION statement)? This prevents redundant data and would make data maintenance easier (e.g. when a nomination is deleted from one of the type-specific table, it automatically vanishes from the ALL_NOMINATIONS view, etc.).

PHP - for statement in an array

For a PDO execution statement I am trying to make any static information such as column names and array strings to a dynamic array which contains every column from the MySQL table.
The original code was:
$stmt = $conn->prepare("INSERT into data (`username,` `password`, `email`) VALUES username = :username , password = :password , email = :email ");
$stmt->execute(array(
':username' => $entry_username,
':password' => $entry_password,
':email' => $entry_email
));
So far I have been able to change the sql statement to
$sql = "INSERT into DATA (`" . implode('`,`', $columns) . "`) values (:" . implode(',:', $columns) . ")";
$stmt = $conn->prepare($sql);
but have been unable to do a similar thing to the execution array to make it dynamically variating like the statement.
I have tried adding a for statement in the array
for ($i = 0; $i < count($columns); $i++) {
':'.$columns[$i] => ${'entry_'.$columns[$i]};
}
but this hasn't worked.
Any help would be much appreciated.
Thanks in advance!
This is a perfect situation to make good use of a prepared statement.
Try this:
I am kind of assuming what the varuables will be called in the $columns array here.
$stmt = $conn->prepare("INSERT into data
(username, password, email) VALUES( :username , :password, :email )");
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
foreach ( $columns as $column ) {
$username = $column['username'];
$password = $column['password'];
$email = $column['email'];
$result = $stmt->execute();
if ( ! $result ) {
// add some error checking code here
}
}
Basically, your code would look like this.
$entry = array(
'username' => $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement
'password' => $_POST['password'],
'email' => $_POST['email']
);
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);
$sth->execute();
If you want the bound variables to be dynamically created, then you need to create with a loop the bindValue rows:
$entry = array(
'username' => $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement
'password' => $_POST['password'],
'email' => $_POST['email']
);
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
foreach($entry as $key => $value) {
$sth->bindValue(':'.$key, $entry[$key], PDO::PARAM_STR);
}
$sth->execute();
or inside the foreach
$sth->bindValue(':'.$key, $value, PDO::PARAM_STR);
Since your keys are (username, password, email) their keynames will be initiated to $key variable, and their values to the $value variable. in the first case it will produce:
$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);
Which will be evaluated to:
$sth->bindValue(':username', $_POST['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $_POST['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $_POST['email'], PDO::PARAM_STR);
In the second case it will be directly evaluated.
Have in mind it's completely unacceptable to dynamically create the column names in the query. And you have to reason to do it. However, not a full query is also hard to be read from the other developers. It's enough for you to dynamically create the bound values. You can make a method do it for you. For instance, if you column names in the query are the same way aliased, as the names of the input fields, you will have nothing more to do, but to execute the query.
Let's say you have that helper method:
Class DBConnect {
private $_driver = "mysql";
private $_dbname = "xxxx";
private $_host = "xxxx";
private $_user = "xxxx";
private $_password = "xxxx";
private $_port = 3306;
private $_dbh;
public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
$driver = $driver ?: $this->_driver;
$dbname = $dbname ?: $this->_dbname;
$host = $host ?: $this->_host;
$user = $user ?: $this->_user;
$pass = $pass ?: $this->_password;
$port = $port ?: $this->_port;
try {
$this->_dbh = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
$this->_dbh->exec("set names utf8");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
public function query($sql) {
$sth = $this->_dbh->prepare($sql);
foreach ($_REQUEST as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
$sth->bindValue(":$key", $value, $param);
}
$sth->execute();
$result = $sth->fetchAll();
return $result;
}
}
So, lets say in another class you have a lot of queries, separated by methods:
public function getFirstQuery() {
$sql = "SELECT
col1, col2
FROM table1
WHERE col3 = :col3;";
$query = $this->_db->query($sql);
return $query;
}
public function inserSecondquery() {
$sql = "INSERT INTO
`table1`
(col1, col2)
VALUES
((SELECT
id
FROM table2
WHERE col8 = :col8), :post_field_5);";
$query = $this->_db->query($sql);
return $query;
}
Assuming you have called these queries the query() method which also fetches the data, the select one you can foreach to retrieve the data, and the insert one you can just call, to insert data. The only rule here is the post fields should be named same way, for example <input name="post_field_5" />
You can also take a look here: PDO Dynamic Query Building
OK, it seems you need to find library for active record like the ones CodeIgniter uses, or... use CodeIgniter.
From the official documentation:
http://ellislab.com/codeigniter/user-guide/database/helpers.html
$this->db->insert_string();
This function simplifies the process of writing database inserts. It
returns a correctly formatted SQL insert string. Example: $data =
array('name' => $name, 'email' => $email, 'url' => $url);
$str = $this->db->insert_string('table_name', $data);
The first parameter is the table name, the second is an associative
array with the data to be inserted. The above example produces: INSERT
INTO table_name (name, email, url) VALUES ('Rick', 'rick#example.com',
'example.com')
So, in your case, you can have something like this:
<form action="" method="post">
<input type="text" name="username" value="testUser123" />
<input type="password" name="password" value="yourPass666" />
<input type="text" name="email" value="email#example.com" />
<input type="submit" value="submit" />
</form>
<?php
//... extending CI
//... opening a method
$table = 'data';
//comming from somewhere, let's dynamically populated array but for testing purpose I will hardcode:
$columns('username', 'password', 'email');
foreach($columns as $column) {
$data[$column] = $_POST[$column]; // this will produce $data=array('username'=>$_POST['username'],password=....);
}
$str = $this->db->insert_string($table, $data);
?>
If you submit the form in the beginning, you will have:
INSERT INTO data (username, password, email) VALUES ('testUser123', 'yourPass666', 'email#example.com');
The whole active record class doc (insert chosen here)
http://ellislab.com/codeigniter/user-guide/database/active_record.html#insert
If you don't have to stick to the for loop, I would suggest a foreach, which should be easier (I know the little problems with for too).
foreach ($element in $array)
{
code execution here
}
Your array element is then stored in the $element (or as you like to name it) and you can execute the command found there.
Is this what you're looking for or did I get you wrong?

adding error msg to prepared statements

I'm trying to convert mysql_query over to prepared statements, but it's failing silently and I'm not sure where I'm going wrong. Here's my proc.php page for a form:
$db = new PDO('mysql:host=XXX;dbname=XXX;charset=utf8', 'XXX', 'XXX');
if ($_POST['submit']) {
$type = $_POST['type'];
$auth1_lname = trim($_POST['auth1_lname']);
$auth1_fname = trim($_POST['auth1_fname']);
$today = date("Y-m-d");
$stmt = $db->prepare("INSERT INTO table_base ( type , publ_date , auth1_lname , auth1_fname )
VALUES (:type, :today, :auth1_lname , :auth1_fname) ");
$stmt->bindParam(':type', $type);
$stmt->bindParam(':today', $today);
$stmt->bindParam(':auth1_lname', $auth1_lname);
$stmt->bindParam(':auth1_fname', $auth1_fname);
$stmt->execute();
$bid = $db->lastInsertId();
$subj_area = $_POST['subj_area'];
$subject = 'subj_area';
$subjs = '';
$stmt = $db->prepare("INSERT INTO table_meta (bid, key, value) VALUES (:bid, :key, :value)");
$stmt->bindParam(':bid', $bid);
$stmt->bindParam(':key', $subject);
$stmt->bindParam(':value', $subjs, PDO::PARAM_STR);
foreach($subj_area as $subjs) {
$stmt->execute();
}
$geo_area = $_POST['geo_area'];
$geograph = 'geo_area';
$geos = '';
$stmt = $db->prepare("INSERT INTO table_meta (bid, key, value) VALUES (:bid, :key, :value)");
$stmt->bindParam(':bid', $bid);
$stmt->bindParam(':key', $geograph);
$stmt->bindParam(':value', $geos, PDO::PARAM_STR);
foreach($geo_area as $geos) {
$stmt->execute();
}
}
I'm not sure I'm even doing this right.
I see comments elsewhere on SO that your PHP must be this tall to use PDO, but php.net's page on PDO doesn't list PHP requirements. Am I failing b/c my PHP5 host doesn't have the right drivers?
Is there a way to add a die(mysql_error()) so at least it wouldn't be a silent failure?

How to edit many values # one time in PHP

I'm trying to edit many columns at one time. I have a lot of fields that I want users to be able to edit. I'm not sure exactly what I'm doing incorrectly. Any help would be greatly appreciated. It states that There was a problem with your mySQL query please contact technical support with the following information:
<?php
$dbserver = "";
$dblogin = "";
$dbpassword = "";
$dbname = "";
$con = mysqli_connect("$dbserver","$dblogin","$dbpassword","$dbname");
if (!$con)
{
die('Could not connect to the mySQL server please contact technical
support with the following information: ' . mysqli_connect_errno());
}
$organization = mysqli_real_escape_string($_POST['organization']);
$firstname = mysqli_real_escape_string($_POST['firstname']);
$lastname = mysqli_real_escape_string($_POST['lastname']);
$rank = mysqli_real_escape_string($_POST['rank']);
$branch= mysqli_real_escape_string($_POST['branch']);
$gender= mysqli_real_escape_string($_POST['gender']);
$emailaddress = mysqli_real_escape_string($_POST['emailaddress']);
$jobtitle = mysqli_real_escape_string($_POST['jobtitle']);
$company = mysqli_real_escape_string($_POST['company']);
$businessphone = mysqli_real_escape_string($_POST['businessphone']);
$homephone = mysqli_real_escape_string($_POST['homephone']);
$mobilephone = mysqli_real_escape_string($_POST['mobilephone']);
$faxnumber = mysqli_real_escape_string($_POST['faxnumber']);
$address = mysqli_real_escape_string($_POST['address']);
$city = mysqli_real_escape_string($_POST['city']);
$state = mysqli_real_escape_string($_POST['state']);
$zippostal = mysqli_real_escape_string($_POST['zippostal']);
$country = mysqli_real_escape_string($_POST['country']);
$notes = mysqli_real_escape_string($_POST['notes']);
$donorid = mysqli_real_escape_string($_POST['donorid']);
// make the query a variable so we can print out if it fails
$query = "UPDATE donors SET organization = '$organization', firstname =
'$firstname', lastname = '$lastname', rank = '$rank', branch = '$branch',
gender = '$gender', emailaddress = '$emailaddress', jobtitle = '$jobtitle',
company = '$company', businessphone = '$businessphone', homephone =
'$homephone', mobilephone = '$mobilephone', faxnumber = '$faxnumber', address =
'$address', city = '$city', state = '$state', zippostal = '$zippostal', country
= '$country', notes = '$notes', donorid = '$donorid' WHERE donorid =
'$donorid'";
$sql = mysqli_query($con,$query) or die('There was a problem with your mySQL
query please contact technical support with the following information: ' .
mysqli_error());
// troubleshooting for development only
if(mysqli_affected_rows($sql) < 1){
die('There was a problem with your mySQL query : ' . $query);}
mysqli_close($con);
header( 'Location: http://localhost/moddonor.php' ) ;
?>
Based on the conversation on #Sean answer you need to build your query dynmically, something like this should work (also it should be noted im using php5.3+ specific syntax for anon functions with array_map):
// array of field => bind type
$fields = array(
'firstname' => 's',
'lastname' => 's',
'rank' => 'i',
// other fields EXCEPT donorid
);
// template for the sql
$sqlTemplate = 'UPDATE SET %s WHERE donorid = ?';
// array to hold the fields we will actually use with the query
$params = array();
// lets check the fileds against those allowed
// and stick them in the $params array - note we exclude donorid
// because its required
foreach ($fields as $field => $type) {
if(isset($_POST[$field]) && !empty($_POST[$field])) {
$params[$field] = array(
'value' => $_POST[$field],
'type' => $type
);
}
}
// if we actually have something to update then lets prep the sql
if(!empty($params)) {
$forUpdate = array_map(function ($f) { return $field . ' = ?'; }, array_keys($params));
$sql = sprtintf($sqlTemplates, implode(',', $forUpdate));
// $sql is now the parameterized query like my example below
// compile all the parameter types into a single string like 'ssi'
$types = implode('', array_map(function($v){ return $v['type'];}, $params));
// now we need to push the $stmt and the $types onto $params
array_unshift ($params, $stmt, $types);
// params now looks like:
// Array ( 0 => Msqil_Stmt, 1 => 'ssi', 'firstname' => 'thevalue', 'lastname' => 'value', 'rank' => 1, etc..)
// now call bindparam via call_user_func_array
call_user_func_array('mysql_stmt_bind_param', $params);
// now execute the query:
mysqli_stmt_execute($stmt);
}
Youre doing muiltiple things wrong:
you are using both mysql_* and mysqli_* they are not interchangeable. Use mysqli_* because mysql_* is deprecated ans shouldnt be used anymore; All your mysql functions should be the mysqli versions.
You need quotes around your values and you also need to escape those values. Since youre using mysqli use prepared statements.
The resource connection is the second argument to the query functions, not the first.
--
// with mysqli the db name is passed as an argument wen creating the connection
$con = mysqli_connect("$dbserver","$dblogin","$dbpassword", $dbname);
if (!$con) {
die('Could not connect to the mySQL server please contact
technical support with the following information: ' . mysqli_error());
}
$sql = "UPDATE donors set organization = ?, firstname =
?, lastname = ?, rank = ?, branch = ?,
gender = ?, emailaddress = ?, jobtitle = ?, company
=?, businessphone = ?, homephone = ?,
mobilephone =?, faxnumber = ?, address = ?, city =
?, state = ?, zippostal =?, country = ?,
note = ?
WHERE donorid= ?";
$stmt = mysqli_preapre($sql);
mysqli_bind_param($stmt,
'ssisss...i',
$organization,
$firstname,
$lastname,
$rank,
$branch,
$gender,
$emailaddress,
// other feilds... the must be in the same order as named in the query
// then lastly the donorid
$donorid
);
// execute the query
mysqli_stmt_excecute($stmt);
mysqli_close($con);
header( 'Location: http://localhost/moddonor.php' ) ;
You are connecting using mysql_connect(), but using mysqli_query(). You also need to enclose your values in quotes '/"
$con = mysql_connect("$dbserver","$dblogin","$dbpassword");
...
mysql_select_db("$dbname", $con);
...
mysqli_query($con,"UPDATE donors set organization = '$organization', firstname =
'$firstname', lastname = '$lastname', rank = '$rank', branch = '$branch',
gender = '$gender', emailaddress = '$emailaddress', jobtitle = '$jobtitle', company
='$company', businessphone = '$businessphone', homephone = '$homephone',
mobilephone = '$mobilephone', faxnumber = '$faxnumber', address = '$address', city =
'$city', state = '$state', zippostal = '$zippostal', country = '$country',
note = '$note' WHERE donorid= '$donorid'");
mysqli_close($con);
Change your connection to mysqli_connect() as mysql_ functions are depreciated.
$con = mysqli_connect("$dbserver", "$dblogin", "$dbpassword", "$dbname");
if (!$con)
{
die('Could not connect to the mySQL server please contact
technical support with the following information: ' . mysqli_error());
}
mysqli_query($con,"UPDATE donors set organization = '$organization', firstname =
'$firstname', lastname = '$lastname', rank = '$rank', branch = '$branch',
gender = '$gender', emailaddress = '$emailaddress', jobtitle = '$jobtitle', company
='$company', businessphone = '$businessphone', homephone = '$homephone',
mobilephone = '$mobilephone', faxnumber = '$faxnumber', address = '$address', city =
'$city', state = '$state', zippostal = '$zippostal', country = '$country',
note = '$note' WHERE donorid= '$donorid'");
Also, it would be beneficial to learn how to do prepared statements - http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
see - http://php.net/manual/en/mysqlinfo.api.choosing.php
or http://www.php.net/manual/en/faq.databases.php#faq.databases.mysql.deprecated
EDIT
Apparently you are not setting your variables before using them in your query. note: make sure to sanitize any user inputs. see mysqli_real_escape_string()
//Put this after $con = mysqli_connect(), but before mysqli_query()
$organization = mysqli_real_escape_string($_POST['organization']);
$firstname = mysqli_real_escape_string($_POST['firstname']);
$lastname = mysqli_real_escape_string($_POST['lastname']);
....
$donorid = mysqli_real_escape_string($_POST['donorid']);
// need to add the rest of your form inputs
EDIT 2
On your updated script there are some issues - organization = $_POST['$organization'], $firstname = $_POST['$firstname'], mysql_error(), etc. Try using the following code edit.
<?php
$dbserver = "";
$dblogin = "";
$dbpassword = "";
$dbname = "";
$con = mysqli_connect("$dbserver","$dblogin","$dbpassword","$dbname");
if (!$con)
{
die('Could not connect to the mySQL server please contact technical support with
the following information: ' . mysqli_connect_errno());
}
$organization = mysqli_real_escape_string($_POST['organization']);
$firstname = mysqli_real_escape_string($_POST['firstname']);
$lastname = mysqli_real_escape_string($_POST['lastname']);
$rank = mysqli_real_escape_string($_POST['rank']);
$branch= mysqli_real_escape_string($_POST['branch']);
$gender= mysqli_real_escape_string($_POST['gender']);
$emailaddress = mysqli_real_escape_string($_POST['emailaddress']);
$donorid = mysqli_real_escape_string($_POST['donorid']);
// make the query a variable so we can print out if it fails
$query = "UPDATE donors SET organization = '$organization', firstname = '$firstname', lastname = '$lastname', rank = '$rank', branch = '$branch', gender = '$gender', emailaddress = '$emailaddress' WHERE donorid = '$donorid'";
$sql = mysqli_query($con,$query) or die('There was a problem with your mySQL query please contact technical support with the following information: ' . mysqli_error());
// troubleshooting for development only
if(mysqli_affected_rows($sql) < 1){
die('There was a problem with your mySQL query : ' . $query);}
mysqli_close($con);
header( 'Location: http://localhost/moddonor.php' ) ;
You didnt mention whats the error but,
I think you must wrap the values using single quote ('), for example
set organization = $organization
becomes
set organization = '$organization'

Is this bad practice for inserting data into db?

I have this function that inserts data from a checkbox into my sql database and it works just find, but Im pretty new to this so I would like to know if there is a better/safer (from sql injections) way to do this. I know I should be using PDO with prepared statements, but that is something I am tackling later.
Here is the form that produces the html checkboxes:
<form action="" method="post">
<?php
if(empty($clients) === true){
echo '<p>You do not have any clients yet.</p>';
}
else
{
foreach($clients as $client){
echo'
<input type="checkbox" name="client_data[]" value="'.$_SESSION['user_id'].'|'.$class_id.'|'.$client['first_name'].'|'.$client['nickname'].'|'.$client['last_name'].'">
'.$client['first_name'].' ('.$client['nickname'].') '.$client['last_name'].'
<br />';
} // foreach($client
} // if empty
?>
Here is the php that calls the function:
if (isset($_POST['exist_to_class'])){
if (empty($_POST['client_data']) === true){
$errors [] = 'You much select a client to be added to the class.';
} else {
if (isset($_POST['client_data']) && !empty($_POST['client_data']));
foreach ($_POST['client_data'] as $cd){
exist_client_to_class($cd);
header('Location: view_class.php?class_id='.$class_id.' ');
} // foreach $cd
} // else
} //isset
And here is my function that inserts the data into the db:
// add existing client to class ----------------------------------------------------
function exist_client_to_class($cd){
list($user_id, $class_id, $first_name, $last_name, $nickname) = explode('|', $cd);
mysql_query("INSERT INTO `clients` (user_id, class_id, first_name, last_name, nickname, date)
VALUES('$user_id', '$class_id', '$first_name', '$last_name', '$nickname', CURDATE())");
}
First stab at a PDO prepared statement:UPDATE
function exist_client_to_class($cd){
try{
$stmt = $conn->prepare('INSERT INTO clients
(user_id, class_id, first_name, last_name, nickname, date)
VALUES (:user_id, :class_id, :first_name, :last_name, :nickname, CURDATE())
');
list($user_id, $class_id, $first_name, $last_name, $nickname) = explode('|', $cd);
$stmt->execute(array(
':user_id' => $user_id,
':class_id' => $class_id,
':first_name' => $first_name,
':last_name' => $last_name,
':nickname' => $nickname
)
);
}
catch(PDOException $e) {
echo 'Error: ' . $e->getMessage();
}
}
Here is the db connect file:
//PDO database connect
try {
$conn = new PDO('mysql:host=localhost;dbname=customn7_cm', '**********', '**********');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("SET CHARACTER SET utf8");
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
To put simply, Yes.
You aren't sanitizing or escaping your user data in anyway. you are using the old mysql_* community deprecated functions. You're best bet is to start using PDO or Mysqli
Read this article: PHP Database Access: Are You Doing It Correctly?
This works for most sql injections: (from php.net)
decleration:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier = NULL ] )
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password') OR die(mysql_error());
// Query
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));

Categories