2010-07-18 71 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