2010-07-18 21 views
12

Quindi sto provando a creare una funzione che genera una stringa di query SQL basata su un array multidimensionale.PHP Array associativo Implode

Esempio:

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

come potete vedere ho bisogno di aiuto con la linea 3 in quanto è in corso di stampa

SELECT MATR, nome utente FROM tabella WHERE cognome E codice postale

ma dovrebbe stampare

SELECT MATR, nome utente FROM tabella WHERE cognome = 'doe' E zipcode = '12345'

+1

Vedo che stai cercando di creare un generatore di query SQL. In questo momento ti dirò che questo è un enorme dolore nel sedere ... Tra l'altro questo genererà SQL non valido se il tuo '$ conditionalArray' è vuoto (dato che la clausola WHERE sarà ancora lì) ... E tu non sei accomodante LIKE, <>, ecc. – quantumSoup

risposta

16

In realtà non stai implodendo un array multidimensionale. $ condizioni è un array associativo.

Basta usare un ciclo foreach all'interno della funzione createQueryString(). Qualcosa del genere dovrebbe funzionare, notare è testato .:

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

Nota: per evitare SQL injection, i valori dovrebbero essere fuggiti e/o quotata come appropriato/necessario per il DB impiegato. Non limitarti a copiare e incollare; pensare!

+1

Probabilmente vuoi mettere dei punti tra i valori – aidan

+0

@aidan In realtà, I non. Il punto della risposta è concentrarsi sul ciclo/logica necessaria per eseguire l'attività. –

+1

Non specificamente, solo una nota per chiunque abbia intenzione di copiare e incollare il codice (perché richiede solo l'iniezione SQL). – aidan

2

Si dovrà scrivere un'altra funzione per elaborare il $conditionalArray, vale a dire l'elaborazione del $key => $value e la gestione dei tipi, per esempio applicare le virgolette se sono una stringa.

Hai appena a che fare con lo stato =? Che dire di LIKE, <, >?

1

Vorrei sconsigliare la creazione di condizionali automatici.
Il tuo caso è troppo locale, mentre ci possono essere molti altri operatori: LIKE, IN, TRA, <, ecc.
Alcune logiche tra cui diversi AND e OR.

Il modo migliore è la via manuale.
Sono sempre fare queste cose in questo modo

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

Anche se si vuole ancora con questo semplice array, basta iterare utilizzando

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

e poi unire queste variabili nel modo in cui si ha bisogno. avete 2 opzioni: create un altro array con le coppie field='value' e poi implodetelo, o semplicemente concatenate, e il sottostrato AND alla fine.

+0

cosa è 'mesc' Non riesco a vedere per trovarlo nei manuali MySQL/PHP – aslum

+0

@aslum che è mysql_real_escape_string –

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

[...] 

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

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

Non testato, ma qualcosa del genere dovrebbe funzionare. In questo modo puoi anche controllare se $ item è un array e usare IN per quei casi.

2

Perdonami se non è troppo 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); 

Quindi l'uscita sarà come qc:

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

fallirà su 'array_flip' quando due chiavi diverse avranno lo stesso valore. – felixRo

0

Io uso una variante di questo:

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

E 'ruvido, ma funziona.

+0

Questo effettivamente lascia la '$ colla 'alla fine. Attualmente uso qualcosa di simile, aggiungendo '$ str = substr ($ str, 0, -strlen ($ glue));' risolve il problema come previsto. –

0

Ecco una versione di lavoro:

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

So che questo è per il caso di un tipo mysql PDO .. ma quello che faccio è costruire metodi DOP involucro, e in questo caso lo faccio funzione che aiuta a costruire la stringa, dal momento che lavoriamo con le chiavi, non esiste un modo possibile per iniettare mysql, dal momento che conosco le chiavi che definisco/accetto manualmente.

immaginare questi dati:

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

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

poi il costruttore matrice di query bind (potrei usare riferimento di matrice diretta ma consente di semplificare):

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

quindi si esegue ...

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

Si potrebbe anche andare per un aggiornamento facile con ...

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

Ma la parte più importante è la funzione serialize_type

-1

Prova questo

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

Dovresti descrivere cosa questo fa in modo diverso o migliore delle risposte degli altri. Così com'è "Prova questo" è piuttosto inutile. – Eiko