This is sort of a follow up to my last question. Im trying to access the data of a multidimensional array so as to insert into a database. Ive been looking all over the forums as well as trying different things on my own but cant find anything that works. Here is what the array looks like:
$_POST[] = array[stake](
'stakeholder1' => array(
'partner'=> 'partner',
'meet'=> 'meet'
),
'stakeholder2' => array(
'partner'=> 'partner',
'agreement'=> 'agreement',
'train'=> 'train',
'meet'=> 'meet'
),
);
I'm trying to do somthing like ( UPDATE list WHERE stakeholder = "stakeholder1" SET partner =1, meet =1 ) depending on which stakeholder/choices were selected (theres four different options). Thanks,
This one will set 1 for checked options, and 0 for unchecked options (otherwise you will miss some data updates).
$optionsList = array('partner', 'agreement', 'train', 'meet');
$stakeHolders = array('stakeholder1', 'stakeholder2', ...);
foreach($stakeHolders as $stakeHolder)
{
$selectedOptions = $_POST[$stakeHolder];
$arInsert = array();
foreach($optionsList as $option)
$arInsert[] = '`'.$option.'` = '.intval(isset($selectedOptions[$option]));
$sql = "UPDATE list
SET ".implode(", ", $arInsert)."
WHERE stakeholder = '".mysql_real_escape_string($stakeHolder)."'";
// TODO: execute $sql (mysql_query(), or PDO call,
// or any wrapper you use for DB)
}
$query = '';
foreach ($_POST as $k => $v) {
$query .= "UPDATE list WHERE stakeholder = '$k' SET " . implode(" = 1," $v) . ",";
}
$query = substr($query, 0, -2); //Get rid of the final comma
This should give you something like what you are looking for, if I understand your database schema correctly.
If you are using PDO, you could do something like:
foreach($_POST as $stakeholder => $data) {
$sth = $dbh->prepare('UPDATE `list` SET `' . implode('` = 1, `', array_keys($data)) . '` = 1 WHERE stakeholder = ?');
$sth->execute(array($stakeholder));
}
Be sure to sanitize the user input (keys of the data...).
foreach($main_array as $key => $sub_array) {
$sql = 'UPDATE list
WHERE stakeholder = "{$key}"
SET ';
$sets = array();
foreach($sub_array as $column_value)
$sets[] = $column_value." = 1";
$sql = $sql.implode(',', $sets);
}
Related
I have an SQL $query like this;
UPDATE `tags` SET `tags.name` = :name,
`tags.slug` = :slug,
`tags.date_published` = :date_published,
`tags.meta_title` = :meta_title,
`tags.meta_description` = :meta_description,
`tags.meta_keywords` = :meta_keywords
WHERE `tags.id` = :id
And my $values array;
Array
(
[:name] => iphone
[:slug] => iphone
[:date_published] => 2016-03-27
[:meta_title] => iphone Yazıları
[:meta_description] => iphone hakkında son gelişmeler ve faydalı bilgiler.
[:meta_keywords] => iphone yazıları, iphone hakkında bilgiler, iphone haberleri
[:id] => 24
)
I'm trying to update one row with PDO's prepare function;
$sth = $this->db->prepare($query);
$sth->execute($values);
echo "affected rows: ".$sth->rowCount(); // prints 0
return $sth->rowCount() ? true : false;
And I get no errors but rows are not affected after execute the query. Where is my mistake?
mysql tags table
edit:
I'm creating values array like this;
$params = array(
"id", "name", "slug", "date_published",
"meta_title", "meta_description", "meta_keywords");
$values = array();
foreach ($params as $key) {
#$values[$key] = $_POST[$key];
}
And this is how I create the query;
$query = "UPDATE `$table` SET";
$values = array();
/* Add field names and placeholders to query. */
foreach ($params as $key => $value) {
$query .= " `{$table}.{$key}` = :" . $key . ",";
$values[":" . $key] = $value;
}
/* Remove last comma. */
$query = substr($query, 0, -1);
/* Build where condition. */
if ($cond) {
$query .= " WHERE ";
foreach ($cond as $key => $value) {
$query .= " `{$table}.{$key}` = :" . $key . ",";
$values[":" . $key] = $value;
}
/* Remove last comma. */
$query = substr($query, 0, -1);
}
You're escaping the column names incorrectly. For example, the back ticks should not enclose the whole of tags.name, but rather the table and column names separately:
`tags`.`name`
Checking the output of PDO::errorInfo() confirms this (emulated prepares must be set to false in order to see this, however).
General notes:
You don't need to specify the colon prefix for the keys of the array being bound (likewise when explicitly binding columns via bindParam() or bindValue()).
You should avoid using back ticks in your PDO queries. They're a MySQL-specific feature, and PDO is not a SQL abstraction layer (thereby preventing one of the major benefits of PDO - portability).
I have an array like the following:
tod_house
tod_bung
tod_flat
tod_barnc
tod_farm
tod_small
tod_build
tod_devland
tod_farmland
If any of these have a value, I want to add it to an SQL query, if it doesnt, I ignore it.
Further, if one has a value it needs to be added as an AND and any subsequent ones need to be an OR (but there is no way of telling which is going to be the first to have a value!)
Ive used the following snippet to check on the first value and append the query as needed, but I dont want to copy-and-paste this 9 times; one for each of the items in the array.
$i = 0;
if (isset($_GET['tod_house'])){
if ($i == 0){
$i=1;
$query .= " AND ";
} else {
$query .= " OR ";
}
$query .= "tod_house = 1";
}
Is there a way to loop through the array changing the names so I only have to use this code once (please note that $_GET['tod_house'] on the first line and tod_house on the last line are not the same thing! - the first is the name of the checkbox that passes the value, and the second one is just a string to add to the query)
Solution
The answer is based heavily upon the accepted answer, but I will show exactly what worked in case anyone else stumbles across this question....
I didnt want the answer to be as suggested:
tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
rather I wanted it like:
AND (tod_bung = 1 OR tod_barnc = 1 OR tod_small = 1)
so it could be appended to an existing query. Therefore his answer has been altered to the following:
$qOR = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
$qOR[] = "$var = 1";
}
}
$qOR = implode(' OR ', $qOR);
$query .= " AND (" .$qOR . ")";
IE there is no need for two different arrays - just loop through as he suggests, if the value is set add it to the new qOR array, then implode with OR statements, surround with parenthesis, and append to the original query.
The only slight issue with this is that if only one item is set, the query looks like:
AND (tod_bung = 1)
There are parenthesis but no OR statements inside. Strictly speaking they arent needed, but im sure it wont alter the workings of it so no worries!!
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
$qOR = array();
$qAND = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
if (!empty($qAND)) {
$qOR[] = "$var = 1";
} else {
$qAND[] = "$var = 1";
}
$values[] = $_GET[$var];
}
}
$qOR = implode(' OR ', $qOR);
if ($qOR != '') {
$qOR = '(' . $qOR . ')';
}
$qAND[] = $qOR;
$qAND = implode(' AND ', $qAND);
echo $qAND;
This will output something like tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
As the parameter passed to $_GET is a string, you should build an array of strings containing all the keys above, iterating it and passing the values like if (isset($_GET[$key])) { ...
You could then even take the key for appending to the SQL string.
Their are a lot of ways out their
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
if($_GET){
$query = "";
foreach ($_GET as $key=>$value){
$query .= (! $query) ? " AND ":" OR ";
if(in_array($key,$list) && $value){
$query .= $key." = '".$value."'";
}
}
}
Sure you have to take care about XSS and SQL injection
If the array elements are tested on the same column you should use IN (...) rather than :
AND ( ... OR ... OR ... )
If the values are 1 or 0 this should do it :
// If you need to get the values.
$values = $_GET;
$tod = array();
foreach($values as $key => $value) {
// if you only want the ones with a key like 'tod_'
// otherwise remove if statement
if(strpos($key, 'tod_') !== FALSE) {
$tod[$key] = $value;
}
}
// If you already have the values.
$tod = array(
'tod_house' => 1,
'tod_bung' => 0,
'tod_flat' => 1,
'tod_barnc' => 0
);
// remove all array elements with a value of 0.
if(($key = array_search(0, $tod)) !== FALSE) {
unset($tod[$key]);
}
// discard values (only keep keys).
$tod = array_keys($tod);
// build query which returns : AND column IN ('tod_house','tod_flat')
$query = "AND column IN ('" . implode("','", $tod) . "')";
I'm trying to convert an array (key/value) to be an SQL statement.
I'm using MYSQLi like such:
if(!$result = $mysqli->query($sql)){throw new Exception("SQL Failed ".__file__." on line ".__line__.":\n".$sql);}
I have an array like such:
Array
(
[database] => Array
(
[cms_network] => Array
(
[network_id] => 61
[network_name] =>
[network_server_mac_address] => 00:1b:eb:21:38:f4
[network_description] => network
[network_thermostat_reporting_rate] => 5
[network_server_reporting_rate] => 5
[network_data_poll_rate] => 5
[network_created_by] => 38
[network_modified_by] => 1
[network_network_id] => 8012
[network_language] => en
[network_hotel_id] => 68
[network_channel] => 0
[network_deleted] => 0
[network_reported_network_id] => 8012
[network_rooms] => 4
)
)
)
How can I convert [cms_network] to look like this:
$sql = "UPDATE cms_network set network_id='61', network_name='',
network_server_mac_address = '00:1b:eb:21:38:f4', .... WHERE network_id='61'"
I'm more interested in knowing how to concatenate the key=>value pair of the array to be key='value' in my select statement.
Thanks for the help!
If you use the VALUES syntax, you could do it in one fell swoop.
mysql_query("
UPDATE MyTable
( . implode(',', array_keys($array['database']['cms_network'])) . ")
VALUES ('" . implode("','", $array['database']['cms_network']) . "')
");
This, of course, assumes that the data is already escaped.
EDIT: Tidier version that's easier to read and maintain:
$fields = implode(',', array_keys($array['database']['cms_network']));
$values = implode("','", $array['database']['cms_network']);
mysql_query("UPDATE MyTable ($fields) VALUES ('$values')");
I suggest you populate an array with formatted key/value pairs, then implode them at the end. This is an easy way to add the required , between each key/value:
$fields = array();
foreach($array['database']['cms_network'] as $key => $value) {
// add formatted key/value pair to fields array
// e.g. format: network_id = '26'
$fields[] = $key . " = '" . $value . "'";
}
$fields = implode(', ', $fields);
// build your query
$query = "UPDATE cms_network SET " . $fields . " WHERE network_id = " . $array['database']['cms_network']['network_id'] . " LIMIT 1";
// process it...
This will (SQL wise) be inserting every value as a string, which is obviously incorrect with integer columns etc. It should still work anyway, but if not you'll need to put in a conditional statement for whether to wrap the value in quotes or not, like this:
foreach(...) {
if(is_numeric($value))
$fields[] = $key . ' = ' . $value;
else
$fields[] = $key . " = '$value'";
}
Although this should probably relate to your database column type rather than the PHP variable type. Up to you, they should work fine with quotes around integers.
This should work.
$update_query = "UPDATE `cms_network` SET ";
$count = 0;
foreach($array['database']['cms_network'] as $key => $value) {
if ($count != 0) {
$update_query = $update_query.",".$key."=".$value;
} else {
$update_query = $update_query.$key."=".$value;
}
$count++;
}
$update_query = $update_query." WHERE ".cms_network."=".$array['database']['cms_network'];
mysql_query($update_query);
I know for example if you KNOW what parameters to expect you can simply use
$_GET['parameter']
in your MYSQL query. What if you expect 4-5 parameters, however maybe NOT all of them are passed? For example, let's say the user wants to list all the products which have a price more than 20$ and a warranty of 2 years.
The user could have more search options like for example, the product category should be 2 which is for Laptops
now, my question is, should I have many if statements and check for each possible parameter to see if they are set, and if they are then include them in my MYSQL query, or is there a faster way?
thanks in advance
you should try foreach. Something like:
foreach($_GET as $key => $value) {
switch($key) {
case "category":
$str[] = "category = '". mysql_real_escape_string($value) ."'";
break;
case "price":
$str[] = "price > '". mysql_real_escape_string($value) ."'";
break;
case "warranty":
$str[] = "warranty > '". mysql_real_escape_string($value) ."'";
break;
}
}
//create the mysql string with
$str_where = "WHERE " . implode('AND', $str);
you can uset he str_where string to filter the products.
For security reasons I would definitely list the available keys with their datatypes that can be used in the query first.
$keys = array(
'category' => PDO::PARAM_INT,
'price' => PDO::PARAM_INT,
'etc' => PDO::PARAM_STR
);
// all the available keys for the query and their types
$queryStr = "SELECT * FROM `some_table` WHERE `yourCond`='someVal'";
// initial query you have
$userVals = array();
foreach ($_GET as $key => $value) {
$k = strtolower($key);
if (!in_array($k,array_keys($keys)) || empty($value))
// if the key is not listed in the keys array
// or the value is empty we skip it
continue;
$queryStr .= " AND `$k` = :{$k} ";
// modify query
$userVals[$k] = $value;
// and add the key-value pair into user values array
}
$db = new PDO('mysql:host=someHost;dbname=someDB','someUsername','somePassword');
// create DB connection
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
// enable error reporting
$stmt = $db->prepare($queryStr);
// prepare query string
foreach ($userVals as $k => $v) {
$stmt->bindParam(":{$k}",$v,$keys[$k]);
// bind each parameter with the right datatype
}
$stmt->execute();
// and execute the query
When I run the following MySQL query via PHP and all of the elements of $_GET() are empty strings, all the records in the volunteers table are returned (for obvious reasons).
$first = $_GET['FirstName'];
$last = $_GET['LastName'];
$middle = $_GET['MI'];
$query = "SELECT * FROM volunteers WHERE 0=0";
if ($first){
$query .= " AND first like '$first%'";
}
if ($middle){
$query .= " AND mi like '$middle%'";
}
if ($last){
$query .= " AND last like '$last%'";
}
$result = mysql_query($query);
What is the most elegant way of allowing empty parameters to be sent to this script with the result being that an empty $result is returned?
my solution:
$input = Array(
'FirstName' => 'first',
'LastName' => 'last',
'MI' => 'mi'
);
$where = Array();
foreach($input as $key => $column) {
$value = trim(mysql_escape_string($_GET[$key]));
if($value) $where[] = "`$column` like '$value%'";
}
if(count($where)) {
$query = "SELECT * FROM volunteers WHERE ".join(" AND ", $where);
$result = mysql_query($query);
}
There's no point in running a (potentially) expensive query if there's nothing for that query to do. So instead of trying to come up with an alternate query to prevent no-terms being searched, just don't run the search at all if there's no terms:
$where = '';
... add clauses ...
if ($where !== '') {
$sql = "SELECT ... WHERE $where";
... do query ...
} else {
die("You didn't enter any search terms");
}
With your current code, if everything is empty, you will get the WHERE 0=0 SQL which is TRUE for all rows in the table.
All you have to do is remove the if statements...