PHP 内爆关联数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3276639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:12:13  来源:igfitidea点击:

PHP Implode Associative Array

phparraysassociative-arrayimplode

提问by st4ck0v3rfl0w

So I'm trying to create a function that generates a SQL query string based on a multi dimensional array.

所以我试图创建一个基于多维数组生成 SQL 查询字符串的函数。

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

如您所见,我需要有关第 3 行的帮助,因为它目前正在打印

SELECT ID, username FROM table WHERE lastname AND zipcode

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'

SELECT ID, username FROM table WHERE lastname = 'doe' AND zipcode = '12345'

回答by George Marian

You're not actually imploding a multidimensional array. $conditions is an associative array.

你实际上并没有内爆一个多维数组。$conditions 是一个关联数组。

Just use a foreach loop inside your function createQueryString(). Something like this should work, note it's untested.:

只需在函数 createQueryString() 中使用 foreach 循环即可。像这样的东西应该可以工作,请注意它未经测试。:

$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 quotedas appropriate/necessary for the DB employed. Don't just copy and paste; think!

注意:为防止 SQL 注入,应根据所使用的数据库的适当/必要对值进行转义和/或引用。不要只是复制和粘贴;思考!

回答by Morfildur

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.

未经测试,但像这样的东西应该可以工作。通过这种方式,您还可以检查 $item 是否为数组并在这些情况下使用 IN。

回答by sakhunzai

Forgive me if its not too sexy !

如果它不太性感,请原谅我!

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


$x=preg_replace('/^(.*)$/e', ' "=\'". $data[""]."\'" ',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'

回答by yclian

You will have to write another function to process the $conditionalArray, i.e. processing the $key => $valueand handling the types, e.g. applying quotes if they're string.

您将不得不编写另一个函数来处理$conditionalArray,即处理$key => $value和处理类型,例如,如果它们是字符串,则应用引号。

Are you just dealing with =condition? What about LIKE, <, >?

你只是在处理=条件吗?怎么样LIKE<>

回答by Your Common Sense

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.

我建议不要自动创建条件。
您的案例过于本地化,而可能还有许多其他运算符 - LIKE、IN、BETWEEN、<、> 等。
一些逻辑包括多个 AND 和 OR。

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 ANDat the end.

然后以您需要的方式组合这些变量。你有 2 个选择:用field='value'成对制作另一个数组,然后内爆它,或者只是连接,然后 substr 尾随AND

回答by a coder

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.

这很粗糙,但有效。

回答by Mike

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

回答by Miguel

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.

我知道这是针对 pdo mysql 类型的情况..但我所做的是构建 pdo 包装器方法,在这种情况下,我执行此功能有助于构建字符串,因为我们使用键,所以没有可能的方法到 mysql 注入,因为我知道我手动定义/接受的键。

imagine this data:

想象一下这个数据:

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

you defined utils methods...

您定义了 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,",");
}

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

但这里最重要的部分是 serialize_type 函数

回答by Sidney Palmeira

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