I'm new to this site and coding so please go easy on me if you come across some rookie mistakes.
I have a single form that when submitted it inserts data into two separate tables (users, users_addresses). The user address should be linked back to the user by the User's ID.
I have seen a couple different methods that can be used for this type of problem (and none which IC an get to work), but I'm reaching out for help to see which would be the best way.
This is what I have so far:
public function createNewUser($details, $active)
{
$password = $details["password"];
$username = strtolower($details["username" ]);
$firstname = strtolower($details["firstname"]);
$lastname = strtolower($details["lastname" ]);
$email = strtolower($details["email" ]);
$sex = strtolower($details["sex" ]);
$datepicker = strtolower($details["datepicker" ]);
$disabled = ($active) ? "0" : "1";
$address1 = strtolower($details["address1" ]);
$address2 = strtolower($details["address2" ]);
$province = strtolower($details["province" ]);
$city = strtolower($details["city" ]);
$district = strtolower($details["district" ]);
$zipcode = strtolower($details["zipcode" ]);
$
$sql = "INSERT INTO users VALUES (NULL, LOWER('$username'), MD5('$password'), LOWER('$firstname'), LOWER('$lastname'), LOWER('$email'), LOWER('$sex'), LOWER('$datepicker'), 0, NOW(), $disabled, 0)";
$resultSet = $this->db->query($sql);
return $this->db->getInsertId();
$sql = "INSERT INTO users_addresses VALUES (NULL, LOWER('$userid'), LOWER('$address1'), LOWER('$address2'), LOWER('$province'), LOWER('$city'), LOWER('$district), LOWER('$zipcode')";
$resultSet = $this->db->query($sql);
return $this->db->getInsertId();
}
The second query is never executed as you have a return statement before it executing in all conditions. Even if that is corrected, $user_id in second query has not been filled with value obtained from first query. Solution is below:
First
return $this->db->getInsertId();
should be replaced by
$user_id=$this->db->getInsertId();
Second
return $this->db->getInsertId();
should be replaced by
return $user_id
There is quite something wrong / strange with your code:
Don't put variables directly in SQL code, use prepared statements instead.
You are calling strtolower and LOWER on all the data. No need to do it twice.
The second query is never done, because you return before it. That's "unreachable code".
The fix is probably done by replacing the first return $this->db->getInsertId() with $userid = $this->db->getInsertId() and the second one with return $userid.
Good luck and welcome to SO.
Related
I need to have a function that checks for duplicate entries based on the following fields: first_name, last_name and tel
I have tried going through the forum but cant seem to find help.
<?
function do_data_entry($data){
global $conn;
$sql = "INSERT INTO entry_details (reg_type,mem_id,title,first_name,middle_name,last_name,address,tel,email,position,place_work,mem_cat,mem_fee,sub_date,next_date_sub,district,mem_status,mem_status_reason) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('ssssssssssssssssss',$reg_type,$mem_id,$title,$first_name,$middle_name,$last_name,$address,$tel,$email,$position,$place_work,$mem_cat,$mem_fee,$sub_date,$next_date_sub,$district,$mem_status,$mem_status_reason);
//This picks data posted from the code(in a different form below)
if(is_loggedIN() == 'user'){
redirect('../index.php');
}else if(is_loggedIN() == 'admin'){
if(isset($_POST['add_entry'])){
$data['reg_type'] = $_POST['reg_type'];
$data['mem_id'] = $_POST['mem_id'];
$data['title'] = $_POST['title'];
$data['first_name'] = $_POST['first_name'];
$data['middle_name'] = !isset($_POST['middle_name']) ? "" : $_POST['middle_name'];
$data['last_name'] = !isset($_POST['last_name']) ? "" : $_POST['last_name'];
$data['address'] = !isset($_POST['address']) ? "" : $_POST['address'];
$data['district'] = $_POST['district'];
$data['tel'] = !isset($_POST['tel']) ? "" : $_POST['tel'];
$data['email'] = !isset($_POST['email']) ? "" : $_POST['email'];
$data['position'] = !isset($_POST['position']) ? "" : $_POST['position'];
$data['place_work'] = !isset($_POST['place_work']) ? "" : $_POST['place_work'];
$data['mem_cat'] = $_POST['mem_cat'];
$data['mem_fee'] = $_POST['mem_fee'];
$data['sub_date'] = $_POST['sub_date'];
$data['next_date_sub'] = $_POST['next_date_sub'];
$data['mem_status'] = $_POST['mem_status'];
$data['mem_status_reason'] = $_POST['mem_status_reason'];
if(do_data_entry($data)){
$_SESSION['message'] = "Entry created successfully";
redirect('data_entry.php');
}else{
$_SESSION["message"] = "User already exists. Try different name";
}
}
}else{
redirect('../login.php');
}
The most simple and straight solution is to make a primary key composed by first_name + last_name + tel columns.
After that when you will try to insert the exact same combination, the database (whatever would be) constraint will raise an error and insert will fail.
Hope it helps.
EDIT: Another (poorer) solution could be:
Before you do the insert to access a stored sql function which will check for what you want.
The sql function should be something like that:
...
declare #someVariable int
select #someVariable = count(*) from table t
where (t.FirstName = send_parameterFirstName) AND
(t.LasttName = send_parameterLastName) AND
(t.tel = send_parameterTel)
if #someVariable > 0
return -1
else
return 1
....
If you get -1 you don't do the insert .... :)
Of course you should write your own code, but I still think that the primary key is the best solution and the second is just a poor solution.
You can see here how you can access a stored sql function from php:
access sql functions from php
After following the guidance I received from colleagues on my post, I went to the MySQL database using phpMyAdmin, opened the table structure that I wanted to apply the set rules on, selected the columns (first_name, last_name and tel), then below, i selected "Unique", it applied the changes, I selected the columns of my choice again and this time selected "Index". It now works exactly the way I wanted it.
Thanks alot for your support members.
I have a form that returns all of the below data
$name = $_POST['name'];
$description = $_POST['description'];
$type = $_POST['type'];
$env1 = $_POST['environment[com1]'];
$env2 = $_POST['environment[com2]'];
$env3 = $_POST['environment[com3]'];
$hltCode = $_POST['hlType[code]'];
$hltDB = $_POST['hlType[db]'];
$hltWCF = $_POST['hlType[wcf]'];
$tfsID = $_POST['tfsID'];
$release = $_POST['release'];
$createdBy = 'mhopkins';
$updatedBy = 'mhopkins';
This of course leads to a VERY long query like the following
$insertQuery = "INSERT INTO patches (name, description, type, com1, com2, bofa, code, db, wcf, tfsID, release, createdBy, updatedBy) VALUES ('".$name."','".$description."''".$type."','".$envCom1."','".$envCom2."','".$envBofA."','".$hltCode."','".$hltDB."','".$hltWCF."','".$tfsID."','".$release."','".$createdBy."','".$updatedBy."'")
$insertResult = $link->query($insertQuery);
The values section has a LOT of punctuation and many possibilities for typos. If I have my variable names be the same as the field columns, is there an easier/shorter way to do this?
Your code has sql injection vulnerabilities, I wouldn't run that code even from a trusted source.
You can try using an ORM like Idiorm, it will manage the column names and escape variables for you https://idiorm.readthedocs.org/en/latest/models.html?highlight=insert https://github.com/j4mie/idiorm/
require_once 'idiorm.php';
ORM::configure(array(
'connection_string' => 'mysql:host=localhost;dbname=my_database',
'username' => 'database_user',
'password' => 'top_secret'
));
$patch = ORM::for_table('patches')->create($_POST);
$patch->createdBy = 'mhopkins';
$patch->updatedBy = 'mhopkins';
$patch->save();
You could try to use variables to get the data out of $_POST and reuse them in the SQL string.
Like:
<?php
$descriptionFieldName = "description";
$description = $_POST[$descriptionFieldName];
$sql = "INSERT INTO patches ($descriptionFieldName) VALUES ($description);
?>
Not much shorter, well, even longer. Though this way you are only typing the form input name and the SQL column name once.
You can also try mapping an array to do the job for you, something like:
$dbColumnsToValues = array(
'column_1' => $_POST['column1'],
'column_2' => $_POST['column2'],
);
$columns = "'" . implode("',", array_keys($dbColumnsToValues)) . "'";
$values = "'" . implode("',", array_map(array($link, 'escape'), array_values($dbColumnsToValues))) . "'";
$sql = "INSERT INTO `some_table` (".$columns.") VALUES(".$values.")";
Not tested though, but you should get the point.
Also, assuming your $link object has an escape method that will make sure your input won't trigger an sql injection.
Lets assume that you have a table consisting of 3 columns: col0, col1, col2.
If you are inserting all the fields that are present in the table and in the same order, you can omit listing the column names in the query. Like instead of
INSERT INTO `table` (`col0`, `col1`, `col2`) VALUES ("{$val0}", "{$val1}", "{$val2}",);
try
INSERT INTO `table` VALUES ("{$val0}", "{$val1}", "{$val2}");
PS: PLease sanitize the variable values before using them in the query.
I have this sql statement that returns rows from a customer table. The user has the option for searching with what ever they want to type in. I had this working, until I tried to protect against sql injecting by using bindValue. Now I can't get any results to return unless the user leaves the textbox blank. Below is my code.
Model
function searchMyCusts($field, $query){
$data = null;
$msg = null;
$status = null;
$sth = $this->db->prepare("SELECT ".CustomerFields::ID.",".CustomerFields::FirstName.",".CustomerFields::LastName.",".CustomerFields::PhoneNumber." FROM ".CustomerFields::TableName." WHERE '$field' LIKE :query");
$sth->bindValue(':query', $query);
if ($sth->execute()){
$status = "success";
$msg = "Customer entry successfully altered";
$data = $this->smartFetchAll($sth);
}else{
$status = "error";
$msg = "An error occurred. :".$sth->errorInfo()[2];
}
$jsonData = json_encode($this->buildResponseArray($status, $msg, $data));
return $jsonData;
}
In the prepare line at the end I have the values being passed in. Like I said this was working until I attempted to bindValue the query variable.
I would appreciate any insight you may have. Thanks in advance!
Regards
I don't know how could it work before but first of all you need to change
" WHERE '$field' LIKE :query"
to
" WHERE $field LIKE :query"
or
" WHERE `$field` LIKE :query"
You can't use quotes around a column name because it becomes just a literal string which you compare with :query pattern. The query will work but you'll have no rows returned. Either nothing or back ticks.
Secondly $query should contain all necessary wildcard symbols prior to prepare. E.g.
$query = "%new%";
It's not clear whether it's the case from your code
I am getting my variables from form fields using php :
$url=$_POST['url'];
$tags=$_POST['tags'];
$skillArea=$_POST['skill_area'];
$description=$_POST['description'];
$slideshowImageFileName=($_FILES['imageNameSlideshow']['name']);
But when I run my sql insert query, I get an error if one of the variables is empty, so I have taken to write if statements to deal with this to rewrite the query string, but surely, that's not the answer? It seems very messy
if(empty($slideshowImageFileName)){
$query1="INSERT INTO portfolio (item_name,image_path,description,url) VALUES('$itemName','$imageFileName','$description','$url')";
}else{
$query1="INSERT INTO portfolio (item_name,image_path,description,url,slideshow_image_path) VALUES('$itemName','$imageFileName','$description','$url','$slideshowImageFileName')";
}
I suppose you are looking for something like this:
$slideshowImageFileName = (isset($_FILES['imageNameSlideshow']['name']) && !empty($_FILES['imageNameSlideshow']['name'])) ? $_FILES['imageNameSlideshow']['name'] : NULL;
This will check if the name of the slideshowimage is set and not empty. if it is NULL will be assigned to the variable, if its correct the value will be assigned.
You could replace NULL with "" if you want an empty string to be added.
Try to set the value of $slideshowImageFileName to empty string or a single space as your database table will accept, and use the second query always.
if(empty($slideshowImageFileName)){
$slideshowImageFileName = "";
}
$query1="INSERT INTO portfolio (item_name,image_path,description,url,slideshow_image_path) VALUES('$itemName','$imageFileName','$description','$url','$slideshowImageFileName')";
I am agreed with Mr. Ray. But there is another solution apart from that. Probably slideshow_image_path field on the table doesn't allow null. So you may change the attribute by allowing null and it will work.
I'd probably construct a builder if I'm sure I'll get a lot of optional data.
Like this:
$acceptedKeys = array
('item_name',
'image_path',
'description',
'url',
'slideshow_image_path');
$inserts = array();
foreach($_GET as $key => $var) {
if(in_array($key, $acceptedKeys)) {
// clean and validate your keys here!
$inserts[$key] = $var;
}
}
$customKeys = implode(array_keys($inserts), ',');
$customValues = implode($inserts, ',');
$query = "INSERT INTO portfolio ($customKeys) VALUES($customValues)";
There's a few options to this.
Simplest one is to make sure the variables are always set, even if not passed through:
//Set up your database connection as normal, check errors etc.
$db = mysqli_connect($host,$user,$password,$db);
$url = isset($_POST['url']) ? mysqli_real_escape_string($db, $_POST['url']) : "";
$tags= isset($_POST['tags']) ? mysqli_real_escape_string($db, $_POST['tags']) : "";
Escaping data is good practice :) In your INSERT query you'll still need to wrap the values in quotes, or you could do that in the above code as per your preference.
http://uk3.php.net/manual/en/mysqli.construct.php
$lastname = clean($_SESSION['lastname']);
$firstname = clean($_SESSION['firstname']);
$mi = clean($_SESSION['mi']);
$nickname = clean($_SESSION['nickname']);
$studentno = clean ($_SESSION['studentno']);
$password = clean ($_SESSION['password']);
$cpassword = clean ($_SESSION['cpassword']);
$bdate = clean($_POST['bdate']);
$maddress = clean($_POST['maddress']);
$paddress = clean($_POST['paddress']);
$status = clean($_POST['status']);
$religion = clean($_POST['religion']);
$telno = clean($_POST['telno']);
$celno = clean($_POST['celno']);
$email = clean($_POST['email']);
$nationality = clean($_POST['nationality']);
$batch = clean($_POST['batch']);
$dept = clean($_POST['dept']);
$course = clean($_POST['course']);
$achvmnts = clean($_POST['achvmnts']);
$emp = clean($_POST['emp']);
$empadd = clean($_POST['empadd']);
$position = clean($_POST['position']);
$emptelno = clean($_POST['emptelno']);
$empemail = clean($_POST['empemail']);
I have the following INSERT query for the values above where the first 7 are being retrieved from a saved session, everything are declared as varchar except for the fields bdate = date, celno and studentno = bigint, :
$result = mysql_query("INSERT INTO `$dept`(lastname,firstname, mi,nickname,bdate,maddress,paddress,status,religion,telno,celno,email,nationality,password,studentno,batch,dept,course,achvmnts,emp,empadd,position) VALUES
('$lastname','$firstname','$mi','$nickname','$bdate', '$maddress','$paddress','$status,','$religion','$telno',$celno,'$email','$nationality','$password',$studentno,'$batch', '$dept','$course','$achvmnts','$emp','$empadd,'$position')");
.I can't seem to find the error in this query, for hours i have been receiving "Query Error". can anyone please help me find the error. Thanks in advance!
There is an error in your insert right there:
'$empadd, '$position')");
the 2. quotation is missing
$result = mysql_query("INSERT INTO `$dept`(lastname,firstname, mi,nickname,bdate,maddress,paddress,status,religion,telno,celno,email,nationality,password,studentno,batch,dept,course,achvmnts,emp,empadd,position) VALUES
('$lastname','$firstname','$mi','$nickname','$bdate', '$maddress','$paddress','$status','$religion','$telno',$celno,'$email','$nationality','$password',$studentno,'$batch', '$dept','$course','$achvmnts','$emp','$empadd','$position')");
Should work if thats the problem.
(Edit: removed the , in '$status,' since someone mentioned it in the comments
I don't believe you need the quotations on the INSERT INTO '$dept'. Also, I think your quotations are different, and $studentno has no quotations, I'm not sure if that was intentional. Last, could you post the exact query error
For one thing, this is a ridiculously huge INSERT to be making. Here are things I noted
'$status,', looks incorrect. This would add the status with a trialing comma
'$empadd, is missing a trailing quote
$celno is not placed within quotations. This is risky. All phone numbers should be stored as VARCHAR fields.
Consider using sprintf with mysql_real_escape_string in order to ensure that your variables are formatted correctly. For more information, consult the PHP manual docs on mysql_real_escape_string and sprintf.
The code could be a bit more readable and less open to errors resulting from repetition:
$session_columns = array('lastname','firstname','mi','nickname','studentno',
'password','cpassword');
$post_columns = array('bdate','maddress','paddress','status','religion','telno',
'celno','email','nationality','batch','dept','course','achvmnts','emp',
'empadd','position','emptelno','empemail');
$assignments = array();
foreach ($session_columns as $column)
$assignments[] = sprintf("$column = '%s'", clean($_SESSION[$column]));
foreach ($post_columns as $column)
$assignments[] = sprintf("$column = '%s'", clean($_POST[$column]));
$sql = "INSERT INTO `$dept` SET ".implode(', ', $assignments);