Related
I have written a update function for all tables in php.It works in a very better way .but i think the function is too long . can you please help me to minimize it.Or can you suggest any other easy techniques or methods.
This is my update function
function updatetbl($a,$b,$c)
{
$a=self::data($a);//calling function inside the function
$a.="'WHERE ";
$c=self::data($c);
$c.="'";
$SQL="Update $b set $a $c";
$result=mysqli_query($SQL);
return $result;
}
Where a is data as array ,b is table name,and c is condition.
function data($a)
{
$fields=$a;
$data="";
$separator = '';
foreach($fields as $key=>$value)
{
$data .= $separator . $key . '=\'' . $value;
$separator = '\',';
}
return $data;
}
Use array_walk to loop over the array elements, and implode to combine them into a string.
You also should be using mysqli_real_escape_string() to prevent SQL-injection.
function data($a, $dbcon) {
return implode(', ', array_map(function($val, $column) use($dbcon) {
return "`$column` = '" . mysqli_real_escape_string($dbcon, $val) . "'";
}, $a);
Then you use it like this:
function updatetbl($dbcon, $table, $fields, $wheres) {
$where_string = empty($wheres) ? '' : "WHERE " . self::data($wheres);
$fields_string = self::data($fields);
return mysqli_query($dbcon, "UPDATE `$table` SET $fields_string $where_string";
}
Note that you were missing the first argument to mysqli_query(), the database connection.
Using this array:
$arr=array(
array('project','ProjectId','62c1553d'),
array('project','ProjectName','TEST JSON'),
array('Vendors','PrimeSpec','Fabspec'),
array('Vendors','VendorId','dd759c7f'),
array('Vendors','PrimeSpec','Vendor2'),
array('Vendors','VendorId','Vendor2ID'),
);
The desired result is:
INSERT INTO project (ProjectId,ProjectName) VALUES (62c1553d,'TEST JSON');
INSERT INTO Vendors (PrimeSpec,VendorId) VALUES ('Fabspec',dd759c7f);
INSERT INTO Vendors (PrimeSpec,VendorId) VALUES ('Vendor2',Vendor2ID);
But I'm losing PrimeSpec, Fabspec in the foreach loop - the output I'm getting is:
INSERT INTO project (ProjectId,ProjectName) VALUES (62c1553d,TEST JSON);
INSERT INTO Vendors (VendorId) VALUES (dd759c7f);
Here is my code:
function array2sql($arr){
$sql = '';
$fields = '';
$values = '';
$extable = $arr[0][0];
foreach( $arr as $line ) {
if ($extable == $line[0]) {
$fields .= $line[1].',';
$values .= $line[2].',';
} else {
$sql .= 'INSERT INTO ' . $extable . ' (' . rtrim($fields, ',') . ') VALUES (' . rtrim($values, ',') . ');';
$fields = '';
$values = '';
$extable = $line[0];
}
}
$sql .= 'INSERT INTO ' . $extable . ' (' . rtrim($fields, ',') . ') VALUES (' . rtrim($values, ',') . ');';
echo $sql;
return $arr;
}
array2sql($arr);
I don't understand why it's dropping the first set of data. Thanks for looking at this.
Consider the following simplified version of your array2sql function(using array_walk and array_column functions):
function array2sql($arr) {
$query_data = [];
$sql = "";
array_walk($arr, function($v) use(&$query_data) {
$query_data[$v[0]][$v[1]][] = $v[2];
});
foreach ($query_data as $table => $data) {
$keys = array_keys($data);
$key_string = implode(",", $keys);
$count = count($data[$keys[0]]); // number of values for a certain column
while ($count--) {
$value_string = "'". implode("','", array_column($data, $count)). "'";
$sql .= "INSERT INTO $table($key_string) VALUES($value_string);". PHP_EOL;
}
}
return $sql;
}
print_r(array2sql($arr));
The output:
INSERT INTO project(ProjectId,ProjectName) VALUES('62c1553d','TEST JSON');
INSERT INTO Vendors(PrimeSpec,VendorId) VALUES('Vendor2','Vendor2ID');
INSERT INTO Vendors(PrimeSpec,VendorId) VALUES('Fabspec','dd759c7f');
Seems to be resolved by changing the else statement to
$fields = $line[1].',';
$values = $line[2].',';
Try This
function array2sql($arr){
$sql = '';
$newArr = array();
foreach( $arr as $line ) {
$newArr[$line[0]][$line[1]] = $line[2];
}
foreach($newArr as $tblNam=>$value) {
$sql .= "INSERT INTO ".$tblNam." (`" . implode('`,`', array_keys($value)) . "`) VALUES ('" . implode("','", array_values($value)) . "') ";
}
echo $sql;
}
Because your tables are only receiving two columns of data each, array_chunk() can help to merge and prepare and compose the queries.
$arr=array(
array('project','ProjectId','62c1553d'),
array('project','ProjectName','TEST JSON'),
array('Vendors','PrimeSpec','Fabspec'),
array('Vendors','VendorId','dd759c7f'),
array('Vendors','PrimeSpec','Vendor2'),
array('Vendors','VendorId','Vendor2ID'),
);
// merge and prepare
foreach(array_chunk($arr,2) as $pair){
if(!isset($queries[$pair[0][0]]['columns'])){
$merge[$pair[0][0]]['columns']='`'.implode('`,`',array_column($pair,1)).'`';
}
$merge[$pair[0][0]]['values'][]="'".implode("','",array_column($pair,2))."'";
}
// compose queries
foreach($merge as $table=>$a){
$queries[$table]="INSERT INTO $table ({$a['columns']}) VALUES (".implode('),(',$a['values']).")";
}
print_r($queries);
/*
Array(
[project] => INSERT INTO project (`ProjectId`,`ProjectName`) VALUES ('62c1553d','TEST JSON')
[Vendors] => INSERT INTO Vendors (`PrimeSpec`,`VendorId`) VALUES ('Fabspec','dd759c7f'),('Vendor2','Vendor2ID')
)
*/
$mysqli->multi_query(implode(';',$queries));
while ($mysqli->next_result()) {;} // flush multi_queries
This method performs no escaping or security measures. If you want to use prepared statements and placeholders, a few modifications will be necessary.
For more details on how to write a full mysqli_multi_query() INSERT block, see this link: Strict Standards: mysqli_next_result() error with mysqli_multi_query
I'm using a multiform PHP script given here. It is basically a kind of form completion in multiple steps on the same page. I'm just a beginner in PHP, so I was taking idea from this script.
What I failed to understand is: "How to store the data input by the user in SQL tables?
In the save function, instead of saving data into the $_SESSION (here: $_SESSION[$step][$key] = $val;), save it your SQL database.
But be careful. You will have to update the script to retrieve information from the database instead of from the $_SESSION when you set the value in each input tag.
edit:
The save function is where you will store each data input from user. Instead of :
function save($step, $data) {
//$_SESSION[$step] = $data;
$fields = explode('&',$data);
foreach ($fields as $field) {
$keyVal = explode('=', $field);
$key = urldecode($keyVal[0]);
$val = urldecode($keyVal[1]);
$_SESSION[$step][$key] = $val;
}
}
You should have something like that (the sql queries aren't good, it's just an example):
function save($step, $data)
{
//$_SESSION[$step] = $data;
$fields = explode('&',$data);
$sql = "INSERT INTO `ma_table` (`step`, `key`, `val`) VALUES ";
foreach ($fields as $field)
{
$keyVal = explode('=', $field);
$key = mysql_real_escape_string($keyVal[0]);
$val = mysql_real_escape_string($keyVal[1]);
$sql .= "('" . $step . "', '" . $key . "', '" . $val . "')";
}
mysql_query($sql);
}
how i do wrong i want insert to db data from array:
$tabb = array(
'name' => 'test',
'login' => 'testt');
but i cant use SET, because end of query is char , .
public function insert($table, $values){
if($this->database){
print_r($values);
$we = 'INSERT INTO '. $table .' SET ';
foreach($values as $value => $key) {
$we .= ' ('. $value .' = "'. $key .'") ';
}
print $we;
mysql_query($we);
}
return true;
}
i do print $we:
INSERT INTO user SET (name = "test") (login = "testt")
not work, please help
php
I really recommend avoiding SET. It is far less common and given the choice between something which is uncommon and something which is common, always go with the common -- it means broader, faster, and better support by your community.
Here's how you'd approach that problem without it:
If you only have two columns in your USER table, you can simply use VALUES followed by a comma delineated list of data sets:
INSERT INTO user VALUES ("test","testt"),("test2","testt2")
Your function doesn't look like it is geared towards this, but it is a good thing to know either way.
But it looks like you are inserting by column name (a good idea in general):
INSERT INTO user (name, login) VALUES ("test","testt")
With PHP this becomes:
$items = array_map('mysql_real_escape_string', $values);
$items = '(\'' . implode( '\',\'', $items ) . '\')';
$q = 'INSERT INTO '.
$table .
// using implode with array_keys assumes that you know all of the keys
// ahead of time. If you don't, I MUST suggest your re-think your code
// omit the following line if you want to follow the first SQL example
' (' . implode( ',', array_keys( $values ) . ') '.
' VALUES ' .
$items;
public function insert($table, $values){
$fields = array();
$data = array();
foreach ($values as $key => $val) {
$fields[] = mysql_real_escape_string($key);
$data[] = mysql_real_escape_string($val);
}
$fields = implode(',', $fields);
$data = implode(',', $data)
$sql = "INSERT INTO $table ($fields) VALUES ($data);"
mysql_query($sql) or die(mysql_error());
}
public function insert($table, $values)
{
if($this->database)
{
print_r($values);
$we = 'INSERT INTO '. $table .' SET ';
$sep = '';
foreach($values as $value => $key)
{
$we .= $sep . ' ('. $value .' = "'. mysql_real_escape_string($key) .'") ';
$sep = ',';
}
print $we;
mysql_query($we);
}
return true;
}
Or, if you want to be tricky:
public function insert($table, $values)
{
if($this->database)
{
print_r($values);
$we = "insert into `".$table. "` (`". implode('`,`',array_keys($fields))."`) values ('".implode("','",array_map('mysql_real_escape_string', $fields))."');";
print $we;
mysql_query($we);
}
return true;
}
You need to seperate (name = "test") (login = "testt") with ", " between them (name = "test"), (login = "testt")
Another way is to do it is:
INSERT INTO user (name, login) VALUES ("test", "testt")
So I'm trying to create a function that generates a SQL query string based on a multi dimensional array.
Example:
function createQueryString($arrayToSelect, $table, $conditionalArray) {
$queryStr = "SELECT ".implode(", ", $arrayToSelect)." FROM ".$table." WHERE ";
$queryStr = $queryStr.implode(" AND ",$conditionalArray); /*NEED HELP HERE*/
return $queryStr;
}
$columnsToSelect = array('ID','username');
$table = 'table';
$conditions = array('lastname'=>'doe','zipcode'=>'12345');
echo createQueryString($columnsToSelect, $table, $conditions); /*will result in incorrect SQL syntax*/
as you can see I need help with the 3rd line as it's currently printing
SELECT ID, username FROM table WHERE
lastname AND zipcode
but it should be printing
SELECT ID, username FROM table WHERE
lastname = 'doe' AND zipcode = '12345'
You're not actually imploding a multidimensional array. $conditions is an associative array.
Just use a foreach loop inside your function createQueryString(). Something like this should work, note it's untested.:
$terms = count($conditionalArray);
foreach ($conditionalArray as $field => $value)
{
$terms--;
$queryStr .= $field . ' = ' . $value;
if ($terms)
{
$queryStr .= ' AND ';
}
}
Note: To prevent SQL injection, the values should be escaped and/or quoted as appropriate/necessary for the DB employed. Don't just copy and paste; think!
function implodeItem(&$item, $key) // Note the &$item
{
$item = $key . "=" . $item;
}
[...]
$conditionals = array(
"foo" => "bar"
);
array_walk($conditionals, "implodeItem");
implode(' AND ', $conditionals);
Untested, but something like this should work. This way you can also check if $item is an array and use IN for those cases.
You will have to write another function to process the $conditionalArray, i.e. processing the $key => $value and handling the types, e.g. applying quotes if they're string.
Are you just dealing with = condition? What about LIKE, <, >?
Forgive me if its not too sexy !
$data = array('name'=>'xzy',
'zip'=>'3432',
'city'=>'NYK',
'state'=>'Alaska');
$x=preg_replace('/^(.*)$/e', ' "$1=\'". $data["$1"]."\'" ',array_flip($data));
$x=implode(' AND ' , $x);
So the output will be sth like :
name='xzy' AND zip='3432' AND city='NYK' AND state='Alaska'
I'd advise against automated conditionals creation.
Your case is too local, while there can be many other operators - LIKE, IN, BETWEEN, <, > etc.
Some logic including several ANDs and ORs.
The best way is manual way.
I am always doing such things this way
if (!empty($_GET['rooms'])) $w[]="rooms='".mesc($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mesc($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mesc($_GET['max_price'])."'";
Though if you still want it with this simple array, just iterate it using
foreach ($conditions as $fieldname => $value)...
and then combine these variables in the way you need. you have 2 options: make another array of this with field='value' pairs and then implode it, or just concatenate, and substr trailing AND at the end.
I use a variation of this:
function implode_assoc($glue,$sep,$arr)
{
if (empty($glue)) {$glue='; ';}
if (empty($sep)) {$sep=' = ';}
if (is_array($arr))
{
foreach ($arr as $k=>$v)
{
$str .= $k.$sep.$v.$glue;
}
return $str;
} else {
return false;
}
};
It's rough but works.
Here is a working version:
//use: implode_assoc($v,"="," / ")
//changed: argument order, when passing to function, and in function
//output: $_FILES array ... name=order_btn.jpg / type=image/jpeg / tmp_name=G:\wamp\tmp\phpBDC9.tmp / error=0 / size=0 /
function implode_assoc($arr,$glue,$sep){
$str = '';
if (empty($glue)) {$glue='; ';}
if (empty($sep)) {$sep=' = ';}
if (is_array($arr))
{
foreach ($arr as $key=>$value)
{
$str .= $key.$glue.$value.$sep;
}
return $str;
} else {
return false;
}
}
I know this is for the case of a pdo mysql type.. but what i do is build pdo wrapper methods, and in this case i do this function that helps to build the string, since we work with keys, there is no possible way to mysql inject, since i know the keys i define / accept manually.
imagine this data:
$data=array(
"name"=>$_GET["name"],
"email"=>$_GET["email"]
);
you defined utils methods...
public static function serialize_type($obj,$mode){
$d2="";
if($mode=="insert"){
$d2.=" (".implode(",",array_keys($obj)).") ";
$d2.=" VALUES(";
foreach ($obj as $key=>$item){$d2.=":".$key.",";}
$d2=rtrim($d2,",").")";}
if($mode=="update"){
foreach ($obj as $key=>$item){$d2.=$key."=:".$key.",";}
}
return rtrim($d2,",");
}
then the query bind array builder ( i could use direct array reference but lets simplify):
public static function bind_build($array){
$query_array=$array;
foreach ($query_array as $key => $value) { $query_array[":".$key] = $query_array[$key]; unset($query_array[$key]); } //auto prepair array for PDO
return $query_array; }
then you execute...
$query ="insert into table_x ".self::serialize_type( $data, "insert" );
$me->statement = #$me->dbh->prepare( $query );
$me->result=$me->statement->execute( self::bind_build($data) );
You could also go for an update easy with...
$query ="update table_x set ".self::serialize_type( $data, "update" )." where id=:id";
$me->statement = #$me->dbh->prepare( $query );
$data["id"]="123"; //add the id
$me->result=$me->statement->execute( self::bind_build($data) );
But the most important part here is the serialize_type function
Try this
function GeraSQL($funcao, $tabela, $chave, $valor, $campos) {
$SQL = '';
if ($funcao == 'UPDATE') :
//Formata SQL UPDATE
$SQL = "UPDATE $tabela SET ";
foreach ($campos as $campo => $valor) :
$SQL .= "$campo = '$valor', ";
endforeach;
$SQL = substr($SQL, 0, -2);
$SQL .= " WHERE $chave = '$valor' ";
elseif ($funcao == 'INSERT') :
//Formata SQL INSERT
$SQL = "INSERT INTO $tabela ";
$SQL .= "(" . implode(", ", array_keys($campos) ) . ")";
$SQL .= " VALUES ('" . implode("', '", $campos) . "')";
endif;
return $SQL;
}
//Use
$data = array('NAME' => 'JOHN', 'EMAIL' => 'J#GMAIL.COM');
GeraSQL('INSERT', 'Customers', 'CustID', 1000, $data);