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.
Related
I'm trying to copy a row from a structure I technically know nothing about.
This is what I have so far. This code does work but I'm pretty sure this isn't the most appropriate. Anyone have a better way or a right way of doing this? Any suggestions would be appreciated.
/*
$table is the table name
$id_field is the primary key
$id_value is the row I want to copy
*/
$selectEntity = $dbh->prepare("SELECT * FROM {$table} WHERE {$id_field} = :id_value");
$selectEntity->execute(array(':id_value' => $id_value));
$entity = $selectEntity->fetch(PDO::FETCH_ASSOC);
foreach ($entity as &$value){ if(is_null($value) == true) { $value = "NULL"; } else { $value = "'".htmlspecialchars($value, ENT_QUOTES)."'"; } }
//remove the primary key
$entity[$id_field] = "'"; // the ' was the only way I could get NULL to get in there
$insertCloned = $dbh->prepare("INSERT INTO {$table} (".implode(", ",array_keys($entity)).") VALUES ('".implode(", ",array_values($entity)).")");
$insertCloned->execute();
$lastInsertedID = $dbh->lastInsertId();
It's very messy.
Your quoting is not correct -- you have quotes around the entire VALUES list, they should be around each individual value. Also, you should use $dbh->escape($value) to escape the values; htmlspecialchars is for encoding HTML when you want to display it literally on a web page.
But it's better to use query parameters rather than substituting into the SQL. So try this:
$entity[$id_field] = null;
$params = implode(', ', array_fill(0, count($entity), '?'));
$insertCloned = $dbh->prepare("INSERT INTO {$table} VALUES ($params)");
$insertCloned->execute(array_values($entity));
You don't need to list the column names in the INSERT statement when the values are in the same order as the table schema. And since you used SELECT * to get the values in the first place, they will be.
I have a form that allows users to input classes and activities into multiple fields, these fields are declared like this :
label for ="classact">Classes and Activities</label>
<input type = "text" name = "classact[0]" value ="" id ="classact[0]">
<input type = "text" name = "classact[1]" value ="" id ="classact[1]">
<input type = "text" name = "classact[2]" value ="" id ="classact[2]">
When the form is passed this is the code that handles in the insert:
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('$_POST[name]', '$_POST[city]', '$_POST[phone]', '$photoinfo')
SET #lid = LAST_INSERT_ID()
";
$classactinsert = "INSERT INTO `class_act`
(`cid`";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$temp = $i+1;
$classactinsert = $classactinsert . ",`act$temp`";
}
}
$classactinsert = $classactinsert . ")
VALUES
('#lid'";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$classactinsert = $classactinsert . ",'$_POST[classact][$i]";
}
}
$classactinsert = $classactinsert . ")";
$indata = $maininsert . $classactinsert;
$result = mysql_query($indata);
I realize thats alot of code, but upon filling out the form and submitting this is the query that gets generated:
INSERT INTO `camptest` (`name`, `city`, `phone`, `photo`) VALUES ('Multiple Activities', 'Nowhere', '555-555-1111', 'images/51127f6b06d1e.jpg') SET #lid = LAST_INSERT_ID() INSERT INTO `class_act` (`cid`,`act1`,`act2`,`act3`) VALUES ('#lid','Array[0],'Array[1],'Array[2])
The query is not inserting, but its not throwing back any errors either, even though I have them turned on.
My main question is, what am I doing wrong that is causing the values to act1, act2, and act3 to show up as Array[0], Array[1], and Array[2]?
My secondary question is, am I even going about this the right way? I'm a little new to php and I'm afraid I might be doing this the hard way?
Any help would be appreciated, let me know if you need any additional information.
It does not insert anything, because (among other things) your query string is not being built correctly.
('#lid','Array[0],'Array[1],'Array[2])
The apostrophes are messed up. I'd like to suggest a (in my opinion) cleaner and more structured way to perform your task:
Note: You are obviously working with the mysql_*-stack, so my example is also based on it. But be aware that this is deprecated. Please use mysqli or even better: PDO instead.
<?php
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('{$_POST['name']}', '{$_POST['city']}', '{$_POST['phone']}', '$photoinfo')";
//perform the main insert and fetch the insert id
mysql_query($maininsert);
$last_id = mysql_insert_id();
// Put the keys and values of the acts in arrays. We can already
// populate them with the one key-value-pair we already know
$act_keys = array('cid');
$act_values = array($last_id);
foreach($_POST['classact'] as $key => $value) {
//walk through the POSTed acts and add them to the corresponding array
$act_keys[] = 'act'.($key+1);
$act_values[] = $value;
}
//Now build the whole string:
$insert_acts = "INSERT INTO `class_act`
(`" . implode("`, `", $act_keys) . "`)
VALUES
('" . implode("', '", $act_values) . "')";
//and finally perform the query:
mysql_query($insert_acts);
Please also note that this code is highly vulnerable concerning SQL-Injection and should absolutely not be used in production!!! Make sure to either use prepared statements (like with PDO) or/and to sanitize your input properly.
Also, this solution is just my suggestion and one of many ways to do it. But hey, you asked for an opinion :) PHP is very flexible language, so it's easy to get stuff done, but there are many ways to get it done, so there are always chances to pick a hard an ugly one. Other, especially strong typed languages might prevent that by design. But PHP is really easy to learn and I'm sure your code will improve gradually :)
Another thing I've noticed: You don't need to specify the array-keys in your HTML, you just need to make clear that it's an array with [] behind the name. Also, I'm not sure if the id-attributes you using are valid, but you might want use something more simple:
<input type="text" name="classact[]" value="" id="classact1">
<input type="text" name="classact[]" value="" id="classact2">
<input type="text" name="classact[]" value="" id="classact3">
In the next step, you might want to refactor your code a little to make it even more structured and readable. Since you are performing one task, which is 'inserting something into a table', twice, we could also make a resusable function out of it:
<?php
function my_insert($table, $data) {
// We leverage the flexibility of associative arrays
$keys = "`" . implode("`, `", array_keys($data)) . "`";
$values = "'" . implode("', '", $data) . "'";
mysql_query("INSERT INTO `{$table}` ({$keys}) VALUES ({$values})");
return mysql_insert_id(); //This might come in handy...
}
//in order to use this function, we now put our data into associative arrays:
$class_insert = array(
'name' => $_POST['name'],
'city' => $_POST['city'],
'phone' => $_POST['phone'],
'photo' => $photoinfo
);
$class_insert_id = my_insert('camptest', $class_insert); //and pass it to the function
// You can either build the array while looping through the POSTed values like above,
// or you can pass them in directly, if you know that there will always be 3 values:
$activities_insert = array(
'cid' => $class_insert_id,
'act1' => $_POST['classact'][0],
'act2' => $_POST['classact'][1],
'act3' => $_POST['classact'][2]
);
$activities_insert_id = my_insert('class_act', $activities_insert);
There sure is enough room for improvement and optimization - just wanted to show you how awesome PHP can be :-P
I have a form that takes in a number of fields about a camera's details. This is a custom page I'm creating on Joomla. First I get the database object:
$db = &JFactory::getDBO();
Process the camera name entered in the form and add to DB:
$add_name = $_POST['camera_name'];
$query_insert_camera = "INSERT INTO #__cameras (camera_name, ... , user_id) VALUES ('".mysql_real_escape_string($add_name)."', ... ,'".$user->id."')";
$db->setQuery($query_insert_camera);
$db->query();
I just get an empty string for camera name. If I take out mysql_real_escape_string it works fine. I'm guessing mysql_real_escape_string doesn't like the way I'm establishing a connection...I think.
Any ideas?
You may want to look into JRequest::getVar http://docs.joomla.org/Retrieving_and_Filtering_GET_and_POST_requests_with_JRequest::getVar
However, it doesn't appear that it can be used in a module: http://groups.google.com/group/joomla-dev-general/browse_thread/thread/15ebde03b858c9e8
I just came across the issue of using mysql(i)_real_escape_string() within Joomla, and found that I needed to pass in the db connection as the first parameter:
$db = JFactory::getDbo();
$myVar = JRequest::getVar('myVarName');
$mysqlSafeVar = msqli_real_escape_string($db->getConnection(), $myVar);
$sql = 'INSERT INTO #__mytable (' .$db->nameQuote('myField'). ') VALUES (' . $db->quote($mysqlSafeVar) . ')';
$success = $db->execute();
Your code should work. I see mysql_real_escape_string() being used almost the same way here.
The difference between that code, and what you have is minor, but maybe try something like this instead:
$db = &JFactory::getDBO();
// Escape the POST var as you grab it
$add_name = mysql_real_escape_string(JRequest::getVar('camera_name', '', 'post', 'string'));
$query_insert_camera = "INSERT INTO #__cameras (camera_name) VALUES ('" . $add_name . "')";
$db->setQuery($query_insert_camera);
$db->query();
I'm trying to insert some data into my mysql database. The connection is working fine but im having a problem with sending the query correctly to the database. Below you can find the code in my php file. I also post what for type of fields they are in the Database.
Fields in the mysql database:
Reservaties_id = int
Materialen_id = int
aantal = int
effectief_gebruikt = tinyint
opmerking = Varchar2
datum_van = date
datum_tot = date
$resID = $_REQUEST['resID'];
$materialen_id = $_REQUEST['materialen_id'];
$aantal = $_REQUEST['aantal'];
$effectief_gebruikt = $_REQUEST['effectief_gebruikt'];
$opmerking = $_REQUEST['opmerking'];
$datum_van = date('YYYY-MM-DD',$_REQUEST['datum_van']);
$datum_tot = date('YYYY-MM-DD',$_REQUEST['datum_tot']);
$string = "INSERT INTO `materialen_per_reservatie`(`reservaties_id`, `materialen_id`, `aantal`, `effectief_gebruikt`, `opmerking`, `datum_van`, `datum_tot`) VALUES ($resID, $materialen_id, $aantal, $effectief_gebruikt, '$opmerking', $datum_van, $datum_tot)";
mysql_query($string);
you have to include single quotes for the date fields '$dataum_van'
$string = "INSERT INTO `materialen_per_reservatie`(reservaties_id, materialen_id, aantal, effectief_gebruikt, opmerking, datum_van, datum_tot) VALUES ($resID, $materialen_id, $aantal, $effectief_gebruikt, '$opmerking', '$datum_van', '$datum_tot')";
and this is only a example query, while implementing don't forget to sanitize your inputs
Your code has some serious problems that you should fix. For one, it is not doing any error checking, so it's no surprise the query breaks silently when it fails. Check for errors and it will tell you what goes wrong - how to do it is outlined in the manual on mysql_query() or in this reference question.. Example:
$result = mysql_query($string);
// Bail out on error
if (!$result)
{
trigger_error("Database error: ".mysql_error(), E_USER_ERROR);
die();
}
In this specific case, I'm fairly sure it's because you are not putting your values into quotes after the VALUES keyword.
Also, the code you show is vulnerable to SQL injection. You need to escape every value you use like so:
$resID = mysql_real_escape_string($_REQUEST['resID']);
for this to work, you need to put every value in your query into quotes.
try this
$string = "INSERT INTO `materialen_per_reservatie`(`reservaties_id`) VALUES ('".$resID."')";
$idgen = uniqid(rand(), false);
$churchName = $this->input->post('church_name');
$streetAddress = $this->input->post('street_address');
$locationalCity = $this->input->post('locational_city');
$locationalState = $this->input->post('locational_state');
$locationalZip = $this->input->post('locational_zip');
$locationalCountry = $this->input->post('locational_country');
$taxNum = $this->input->post('tax_exemption_number');**
$this->db->query("INSERT INTO church_repo (church_name, street_address, locational_address, locational_zip, locational_country, locational_city, overseer_account_id, tax_exemption_number, status) VALUES('{$churchName}', '{$streetAddress}', '{$locationalCity}', '{$idgen}', '{$locationalState}', '{$locationalZip}', '{$locationalCountry}', '{$taxNum}', 'pending')");
The code above isn't inserting correctly, in Ci I'm getting the following error:
Error Number: 1054Unknown column 'locational_address' in 'field
list'INSERT INTO church_repo (church_name, street_address,
locational_address, locational_zip, locational_country,
locational_city, overseer_account_id, tax_exemption_number, status)
VALUES('bgtg', 'ff', 'rgfr', '270284f1eec6e5bfd4', 'rgrd', 'bdtbdt',
'United States of America', '84894894894', 'pending')Filename:
C:\Workspace\htdocs\Jan-2012\Gospel-links.org\system\database\DB_driver.phpLine
Number: 330
check your table attribute names, that error means that "locational_address" doesn't exist in your table. may be just a typo
The error is self-explanatory: there's no "locational_address" field, as already pointed out by d2byrke, so you should start by checking that.
Might be "street_address", maybe?
As an addendum, you're not escaping the values you enter in your DB; use query bindings, if you don't want to use Active Record:
$churchName = $this->input->post('church_name');
$streetAddress = $this->input->post('street_address');
$locationalCity = $this->input->post('locational_city');
$locationalState = $this->input->post('locational_state');
$locationalZip = $this->input->post('locational_zip');
$locationalCountry = $this->input->post('locational_country');
$taxNum = $this->input->post('tax_exemption_number');
$sql = "INSERT INTO church_repo(church_name, street_address, locational_address, locational_zip, locational_country, locational_city, overseer_account_id, tax_exemption_number, status) VALUES(?,?,?,?,?,?,?,?,?)";
$this->db->query($sql, array($churchName,$streetAddress,$locationalCity,$locationalState,$locationalZip,$locationalChurch,$taxnum,'pending');
Or, even cleaner (and protected) with Active Record:
$field['church_name'] = $this->input->post('church_name');
$field['street_address'] = $this->input->post('street_address');
$field['locational_city'] = $this->input->post('locational_city');
$field['locational_state'] = $this->input->post('locational_state');
$field['locational_zip'] = $this->input->post('locational_zip');
$field['locational_country'] = $this->input->post('locational_country');
$field['tax_exemption_num'] = $this->input->post('tax_exemption_number');
$field['status'] = 'pending';
$field['overseer_account_id'] = 'value here';
$this->db->insert('church_repo', $field);
Where $field is an array with table names as index, and field values as value.
You need to be sanitizing/escaping that content you are inserting. If there is a ' or something else you'll hit an error. Make sure your DB really does contain locational_address. Copy/paste to make sure no typos.
I would consider changing to this, it's much easier to read and follow whats happening. And the data is properly escaped then.
$data = array(
'church_name' => $this->input->post('church_name'),
'street_address' => $this->input->post('street_address'),
.....
'tax_exemption_number' => $this->input->post('tax_exemption_number')
);
$this->db->insert('church_repo', $data);
Try this just changed the order or insert to mach with column
$idgen = uniqid(rand(), false);
$churchName = $this->input->post('church_name');
$streetAddress = $this->input->post('street_address');
$locationalCity = $this->input->post('locational_city');
$locationalState = $this->input->post('locational_state');
$locationalZip = $this->input->post('locational_zip');
$locationalCountry = $this->input->post('locational_country');
$taxNum = $this->input->post('tax_exemption_number');**
$this->db->query("INSERT INTO church_repo (church_name, street_address, locational_address, locational_zip, locational_country, locational_city, overseer_account_id, tax_exemption_number, status) VALUES('{$churchName}', '{$streetAddress}', '{$locationalCity}', '{$locationalZip}', '{$locationalState}', '{$locationalCountry}', '{$idgen}', '{$taxNum}', 'pending')");