2010-07-18 187 views
12

所以我試圖創建一個函數,生成基於多維數組的SQL查詢字符串。PHP Implode關聯數組

例子:

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*/ 

,你可以看到,我需要與3號線幫助,因爲它是目前印刷

SELECT ID,用戶名FROM表WHERE 姓氏和郵政編碼

但它應該打印

SELECT ID,用戶名FROM表WHERE 姓氏= 'DOE' AND郵政編碼= '12345'

+1

我看到你正在嘗試創建一個SQL查詢構建器。我現在告訴你這是一個巨大的痛苦......順便說一句,如果你的'$ conditionalArray'爲空(因爲WHERE子句仍然在那裏),那麼這將產生無效的SQL ......而你不是適合LIKE,<>等 – quantumSoup 2010-07-18 18:30:14

回答

16

你實際上並沒有內爆多維數組。 $ conditions是一個關聯數組。

只需在函數createQueryString()中使用foreach循環即可。像這樣的東西應該工作,注意這是未經測試:

$terms = count($conditionalArray); 
foreach ($conditionalArray as $field => $value) 
{ 
    $terms--; 
    $queryStr .= $field . ' = ' . $value; 
    if ($terms) 
    { 
     $queryStr .= ' AND '; 
    } 
} 

注意:爲防止SQL注入,值應該逃脫和/或引用適當/必要採用DB。不要複製和粘貼;認爲!

+1

你可能想在值的周圍加上引號 – aidan 2012-10-18 01:15:48

+0

@aidan其實,我不要。答案的重點在於關注完成任務所需的循環/邏輯。 – 2012-10-18 01:53:49

+1

不是你特別的,只是給任何計劃複製和粘貼你的代碼的人的一個提示(因爲它只是要求SQL注入)。 – aidan 2012-10-23 09:21:37

2

你將不得不寫另一個函數來處理該$conditionalArray,即處理$key => $value和處理類型,例如如果他們是字符串,則應用引號。

你剛處理=的條件?那麼LIKE,<,>

1

我建議不要使用自動條件創建。
您的情況太局部了,但可以有許多其他運營商 - 如LIKE,IN,BETWEEN,<,>等。
某些邏輯包括若干個AND和OR。

最好的方法是手動方式。
我一直在做這樣的事情這樣

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'])."'"; 

但如果你還在用這個簡單的陣列想的那樣,只是用

foreach ($conditions as $fieldname => $value)... 

迭代,然後在你需要的方式結合這些變量。你有兩個選擇:用field='value'對創建另一個數組,然後使它崩潰,或者只是連接,並在最後使用substr跟隨AND

+0

什麼是'mesc'我看不到在MySQL/PHP手冊中找到它 – aslum 2011-09-06 17:13:01

+0

@aslum這就是mysql_real_escape_string – 2011-09-06 17:26:46

10
function implodeItem(&$item, $key) // Note the &$item 
{ 
    $item = $key . "=" . $item; 
} 

[...] 

$conditionals = array(
    "foo" => "bar" 
); 

array_walk($conditionals, "implodeItem"); 
implode(' AND ', $conditionals); 

未經測試,但類似這樣的應該工作。這樣你也可以檢查$ item是否是一個數組,並使用IN作爲這些情況。

2

請原諒我,如果它不太性感!

$data = array('name'=>'xzy', 
       'zip'=>'3432', 
       'city'=>'NYK', 
       'state'=>'Alaska'); 


$x=preg_replace('/^(.*)$/e', ' "$1=\'". $data["$1"]."\'" ',array_flip($data)); 

$x=implode(' AND ' , $x); 

所以輸出將某物像:

name='xzy' AND zip='3432' AND city='NYK' AND state='Alaska' 
+0

當兩個不同的鍵具有相同的值時,這將在'array_flip'上失敗。 – felixRo 2016-12-26 21:52:28

0

我用的這個變化:

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; 
    } 
}; 

它的粗糙,但工程。

+0

這實際上在最後留下'$ glue'。我現在使用類似的東西,添加'$ str = substr($ str,0,-strlen($ glue));'按預期修復問題。 – 2014-09-26 18:47:22

0

這裏是一個工作版本:

//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; 
    } 
} 
0

我知道這是一個PDO的MySQL類型的情況下..但我做的是建立PDO包裝方法,在這種情況下,我做這個功能有助於構建字符串,因爲我們使用的鍵,沒有可能的方式來注入mysql,因爲我知道我手動定義/接受的鍵。

想象這樣的數據:

  $data=array(
      "name"=>$_GET["name"], 
      "email"=>$_GET["email"] 
); 

你定義utils的方法...

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,","); 
} 

那麼查詢綁定數組構造器(我可以使用直接序列參考,但可以簡化):

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; } 

然後你執行...

$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)); 

你也可以去更新容易...

$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)); 

但這裏最重要的部分是serialize_type功能

-1

試試這個

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' => '[email protected]'); 
GeraSQL('INSERT', 'Customers', 'CustID', 1000, $data); 
+1

你應該描述一下這些與其他人做出的不同或更好的結果。就目前來看,「試試這個」是無用的。 – Eiko 2016-09-21 20:15:35