I am trying to be lazy (or smart): I have 7 checkboxes which correlate with 7 columns in a MySQL table.
The checkboxes are posted in an array:
$can = $_POST['can'];
I've created the following loop to dump the variables for the MySQL insert:
for($i=1;$i<8;$i++){
if($can[$i] == "on"){
${"jto_can".$i} = 'Y';
}
else{
${"jto_can".$i} = 'N';
}
}
print_r($jto_can1.$jto_can2.$jto_can3.$jto_can4.$jto_can5.$jto_can6.$jto_can7);
This correctly outputs:
YYNYYYY
However, when I attempt to use those variables in my MySQL update, it doesn't accept the changes.
mysqli_query($db, "UPDATE jto SET jto_can1 = '$jto_can1', jto_can2 = '$jto_can2', jto_can3 = '$jto_can3', jto_can4 = '$jto_can4', jto_can5 = '$jto_can5', jto_can6 = '$jto_can6', jto_can7 = '$jto_can7' WHERE jto_id = '$id'")or die(mysqli_error($db));
Can anyone explain why the print_r displays the variables whereas MySQL update does not?
Stick with the array, and form the query dynamically:
$sql = 'UPDATE jto SET ';
$cols = array();
foreach( range( 1, 7) as $i) {
$value = $_POST['can'][$i] == 'on' ? 'Y' : 'N'; // Error check here, $_POST['can'] might not exist or be an array
$cols[] = 'jto_can' . $i . ' = "' . $value . '"';
}
$sql .= implode( ', ', $cols) . ' WHERE jto_id = "' . $id . '"';
Now do a var_dump( $sql); to see your new SQL statement.
this is not a mysql problem. mysql will only see what you put into that string. e.g. dump out the query string BEFORE you do mysql_query. I'm guessing you're doing this query somewhere else and have run into scoping problems. And yes, this is lazy. No it's not "smart". you're just making MORE work for yourself. What's wrong with doing
INSERT ... VALUES jto_can1=$can[0], jto_can2=$can[1], etc...
Related
I'm trying to insert multiple rows with only one INSERT INTO statement using the implode function. I use "keluhanpg" and "mkpg" for multiple values. and "mkpg" uses implode because I use multiple selected data and I implode with comma. like this picture:
enter image description here
<?php
session_start();
include_once('koneksi.php');
if(isset($_POST['add'])){
$kodepg = $_POST['kodepg'];
$noformpg = $_POST['noformpg'];
$waktupg = $_POST['waktupg'];
$deptpg = $_POST['deptpg'];
$lokasipg = $_POST['lokasipg'];
$merkpg = $_POST['merkpg'];
$tahunpg = $_POST['tahunpg'];
$op = isset($_POST['oppg']) && is_array($_POST['oppg']) ? $_POST['oppg'] : [];
$oppg = implode(", ", $op);
$keluhanpg = isset($_POST['keluhanpg']) && is_array($_POST['keluhanpg']) ? $_POST['keluhanpg'] : [];
$mk = isset($_POST['mkpg']) && is_array($_POST['mkpg']) ? $_POST['mkpg'] : [];
$mkpg = implode(", ", $mk);
$shiftpg = $_POST['shiftpg'];
$statuspg = $_POST['statuspg'];
foreach ($_POST['keluhanpg'] as $key => $value){
$sql= "INSERT INTO tb_pg_cs (kode_pg,noform_pg,waktu_pg,dept_pg,lokasi_pg,merk_pg,tahun_pg,op_pg,keluhan_pg,mk_pg,shift_pg,status_pg) VALUES ('" . $kodepg . "','".$noformpg . "','".$waktupg . "','".$deptpg . "','".$lokasipg . "','".$merkpg . "','".$tahunpg . "','".$oppg . "','".$_POST['keluhanpg'][$key] . "','".$mkpg . "','".$shiftpg . "','".$statuspg . "')";
$sql1 = mysqli_query($connect, $sql);
}
if($sql1){
$_SESSION['success'] = 'Data added successfully';
}else{
$_SESSION['error'] = 'Something went wrong while adding';
}
}
header("location: ".$base_url."index.php?page=pengajuan");
?>
the input successfully exited but the "mkpg" data was merged into one. like this:
enter image description here
how to write code to process input correctly?
my MySQL precise version 8.0.3 – vivie
Your version allows to use recursive CTE in SELECT part of INSERT .. SELECT. So you can parse your CSV provided by PHP and store it as a lot of separate rows.
This can be done, for example, using
INSERT INTO test (single_arg, csv_arg)
WITH RECURSIVE
source_data AS ( SELECT #single_arg single_arg,
#csv_arg csv_arg ),
cte AS ( SELECT single_arg,
SUBSTRING_INDEX(csv_arg, ',', 1) single_from_csv,
TRIM(LEADING ',' FROM TRIM(LEADING SUBSTRING_INDEX(csv_arg, ',', 1) FROM csv_arg)) slack_from_csv
FROM source_data
UNION ALL
SELECT single_arg,
SUBSTRING_INDEX(slack_from_csv, ',', 1),
TRIM(LEADING ',' FROM TRIM(LEADING SUBSTRING_INDEX(slack_from_csv, ',', 1) FROM slack_from_csv))
FROM cte
WHERE TRIM(slack_from_csv) <> '' )
SELECT single_arg,
single_from_csv
FROM cte;
See DEMO fiddle (contains some explanations).
In the form, none of the inputs are mandatory. So, I want to have a dynamic "where" clause inside the wpdb query.
Presently this is the query:
$data = $wpdb->get_results($wpdb->prepare("SELECT * FROM
`wp_gj73yj2g8h_hills_school_data` where
`school_zipcode` = %d AND `school_type` = %s AND `school_rating` = %s
;",$selectedZip,$selectedType,$selectedRating));
if a user enters only school_zipcode then the where clause should have only "school_zipcode" column.
Same way for other combinations.
I would not make things complicated with dynamic where clauses... I would write PHP code which creates the query. For example...
NOTE!! THIS CODE IS NOT TESTED ON SERVER, IT'S JUST AN IDEA HOW TO SOLVE THE PROBLEM!
<?php
$where_query = array();
// Make sure to escape $_POST
if (!empty($_POST['school_zipcode')) {
$where_query[] = "school_zipcode='" . $_POST['school_zipcode'] . "'";
}
// Make sure to escape $_POST
if (!empty($_POST['school_type')) {
$where_query[] = "school_type='" . $_POST['school_type'] . "'";
}
// Should result in WHERE school_zipcode='123' AND school_type='text'
$where_query_text = " WHERE " . implode(' AND ', $where_query);
$data = $wpdb->get_results($wpdb->prepare("SELECT * FROM `wp_gj73yj2g8h_hills_school_data` " . $where_query_text . ";"));
I have a form which has multiple drop downs (16) speed[] and some other fields
The data from the dropdown boxes has to be inserted into a Mysql table
What I did is I took the count count($_POST["speed"]);and then loop through until the end of the speed array.
The problem is:
If Anyone of the dropdown is not selected it returns "-1", if used `($_POST["speed"][$i]!="-1")for that but it does not compare and goes into the IF loop
The Insert Query is not a valid not sure how to append the extra commas
$sql when printed
INSERT INTO mytablename (w_name,wtype,speed1,speed2, speed3, speed4, speed5, speed6, speed7, speed8, speed9, speed10, speed11, speed12, speed13, speed14, speed15, speed16, coach_id) VALUES ('name', '', ''-1''800''-1''-1''200''-1''-1''-1''-1''-1''-1''-1''-1''-1''-1''200'', '208')
My PHP code
$itemCount = count($_POST["speed"]);
$itemValues=0;
$query = "INSERT INTO mytablename (w_name,wtype,speed1,speed2, speed3, speed4, speed5, speed6, speed7, speed8, speed9, speed10, speed11, speed12, speed13, speed14, speed15, speed16, coach_id) VALUES ";
$bldSpltString="";
$queryValue = "";
for($i=0;$i<$itemCount;$i++) {
if(($_POST["speed"][$i]!="-1") || !empty($_POST["speed"][$i])) {
$bldSpltString .= "'" . $_POST["speed"][$i] ."'";
}
}
$queryValue .= "('" . $wkout . "', '" . $wtype . "', '" . $bldSpltString . "', '" .$_SESSION['id']."')";
$sql = $query.$queryValue;
echo $sql;
exit;
I would do something like this:
<?php
function dynamicInsert($table_name, $assoc_array){
$keys = array();
$values = array();
foreach($assoc_array as $key => $value){
$keys[] = $key;
$values[] = $value;
}
$query = "INSERT INTO `$table_name`(`".implode("`,`", $keys)."`) VALUES('".implode("','", $values)."')";
echo $query;
}
dynamicInsert("users", array(
"username" => "Test User",
"password" => "Password123"
));
?>
WARNING: This code is not secure, I would run a mysql_real_escape_string and any other necessary sanitation on the variables being sent to mysql. I would also steer clear of allowing this script to run on anything public facing as a dynamic insert could allow for huge security risks!
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) . "')";
Generating the statement elements
I am trying to create an MSSQL prepared statement in a generic way.
Basically, I loop trough the fields, and add them to the prepared SQL string and to the reference parameter (scroll down to see the code).
This results in (names removed):
Prepared query: :
INSERT INTO table
([field],[field],[field],[field],[field],[field],[field],[field],[field],[field],[field],[field],[field],[field],[field],VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
and
sPrepStatement:
return array(&$aLine[0],&$aLine[1],&$aLine[2],&$aLine[3],&$aLine[4],&$aLine[5],&$aLine[6],&$aLine[7],&$aLine[8],&$aLine[9],&$aLine[10],&$aLine[11],&$aLine[12],&$aLine[13],&$aLine[14]);
Preparing the statement
I've tried the following 4 approaches to get this to work with the sqlsrv_prepare statement:
$oSQLStmnt = sqlsrv_prepare($dbhandle, $sPreppedSQL, eval($sPrepStatement));
$fReturnPrepVals = function(){ return eval($sPrepStatement); } ;
$oSQLStmnt = sqlsrv_prepare($dbhandle, $sPreppedSQL, $fReturnPrepVals);
$oSQLStmnt = sqlsrv_prepare($dbhandle, $sPreppedSQL,$aPrepValues);
$oSQLStmnt = call_user_func_array('sqlsrv_prepare',array($dbhandle,$sPreppedSQL, eval($sPrepStatement)));
This either does not work, or inserts blanks into the database.
This is the loop that executes the SQL:
foreach ($aLines as $iLineNum => $sLine) {
$aLine = explode('|', $sLine);
print_r($aPrepValues);
print_r(eval($sPrepStatement));
sqlsrv_execute($oSQLStmnt);
}
The eval($sPrepStatement) works just fine, which makes sense. But I assume it is 'parsed too early' to work in the prepare statement. It should actually only be parsed as the query is executed, but I'm at a loss how to achieve that.
Code for the generation of sql statements:
<?php
//Setup the basic query
$sSql = "INSERT INTO " . $sQName . "\n";
$sFieldNames = "(";
$sValues = "VALUES(";
//This will be evalled to prepare the query, so inserting will be easy.
$sPrepStatement = "return array(";
//FieldIndex to keep track of the current column number
$iFI = 0;
$aLine = array();
foreach ($aSQLQueries[$sQName]['fields'] as $sFieldName => $sQ) {
$sFieldNames .= "[" . $sFieldName . "],";
$sValues .= "?,";
//Init the $aLine var to prevent errors
$aLine[$iFI] = '';
//This will be evalled, so no "" as that would parse it directly
//The values wil be passed by reference
$sPrepStatement .= '&$aLine[' . $iFI . '],';
//Different approach
$aPrepValues[] = &$aLine[$iFI];
$iFI++;
}
$sFieldNames = substr($sFieldNames, 0, -1) . ")";
$sValues = substr($sValues, 0, -1) . ")";
$sPrepStatement = substr($sPrepStatement, 0, -1) . ");";
$sPreppedSQL = $sSql . $sFieldNames . " " . $sValues;
I ended up making it work with PDO, only to find that it could not handle millions of imports at a time, so I eventually used CSV import