2010-07-18 43 views
12

Vì vậy, tôi đang cố tạo một hàm tạo chuỗi truy vấn SQL dựa trên mảng đa chiều.Mảng liên kết mã hóa PHP

Ví dụ:

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

như bạn có thể thấy tôi cần giúp đỡ với dòng thứ 3 là nó hiện in

SELECT ID, tên người dùng FROM table WHERE lastname VÀ mã bưu điện

nhưng cần in

SELECT ID, tên người dùng FROM table WHERE lastname = 'nai' VÀ mã bưu điện = '12345'

+1

Tôi thấy bạn đang cố tạo một trình tạo truy vấn SQL. Tôi sẽ nói với bạn ngay bây giờ đây là nỗi đau lớn trong mông ... Bằng cách này sẽ tạo ra SQL không hợp lệ nếu '$ conditionalArray' của bạn trống (vì mệnh đề WHERE vẫn còn ở đó) ... Và bạn không chứa LIKE, <>, v.v. – quantumSoup

Trả lời

16

Bạn đang không thực sự imploding một mảng đa chiều. Điều kiện $ là một mảng kết hợp.

Chỉ cần sử dụng vòng lặp foreach bên trong hàm của bạn createQueryString(). Một cái gì đó như thế này nên làm việc, lưu ý đó là chưa được kiểm tra .:

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

Lưu ý: Để ngăn chặn SQL injection, các giá trị nên trốn thoát và/hoặc trích dẫn như thích hợp/cần thiết cho DB sử dụng. Không chỉ sao chép và dán; suy nghĩ!

+1

Bạn có thể muốn đặt dấu ngoặc kép xung quanh các giá trị – aidan

+0

@aidan Thực ra, tôi đừng. Điểm của câu trả lời là tập trung vào vòng lặp/logic cần thiết để hoàn thành nhiệm vụ. –

+1

Không phải bạn đặc biệt, chỉ cần một lưu ý cho bất cứ ai lập kế hoạch sao chép và dán mã của bạn (vì nó chỉ yêu cầu cho SQL injection). – aidan

2

Bạn sẽ phải viết chức năng khác để xử lý các $conditionalArray, ví dụ: xử lý $key => $value và xử lý các loại, ví dụ áp dụng dấu ngoặc kép nếu chúng là chuỗi.

Bạn chỉ đang xử lý với điều kiện =? Điều gì về LIKE, <, >?

1

Tôi khuyên bạn không nên tạo điều kiện tự động.
Trường hợp của bạn quá cục bộ, trong khi có thể có nhiều toán tử khác - LIKE, IN, GIỮA, <,> v.v.
Một số logic bao gồm một số AND và OR.

Cách tốt nhất là cách thủ công.
Tôi luôn luôn làm những việc như vậy theo cách này

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

Mặc dù nếu bạn vẫn muốn nó với mảng đơn giản này, chỉ cần lặp nó bằng cách sử

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

và sau đó kết hợp các biến theo cách mà bạn cần. bạn có 2 lựa chọn: tạo một mảng khác với cặp field='value' và sau đó implode nó, hoặc chỉ cần ghép nối, và dấu gạch ngang AND ở cuối.

+0

'mesc' là gì tôi không thể thấy để tìm trong sách hướng dẫn MySQL/PHP – aslum

+0

@aslum đó là 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); 

Chưa được kiểm tra, nhưng một cái gì đó như thế này sẽ hoạt động. Bằng cách này bạn cũng có thể kiểm tra xem $ item có phải là một mảng hay không và sử dụng IN cho những trường hợp đó.

2

Tha thứ cho tôi nếu nó không quá 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); 

Vì vậy, sản lượng sẽ được sth thích:

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

điều này sẽ thất bại trên 'mảng_flip' khi hai khóa khác nhau sẽ có cùng giá trị. – felixRo

0

tôi sử dụng một biến thể của việc này:

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

Đó là khó khăn nhưng hoạt động.

+0

Điều này thực sự để lại '$ keo' ở cuối. Tôi sử dụng một cái gì đó tương tự hiện nay, thêm '$ str = substr ($ str, 0, -strlen ($ keo));' sửa lỗi vấn đề như mong đợi. –

0

Đây là một phiên bản làm việc:

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

Tôi biết đây là đối với trường hợp của một loại mysql PDO .. nhưng những gì tôi làm là xây dựng phương pháp PDO wrapper, và trong trường hợp này tôi làm chức năng này giúp xây dựng chuỗi, kể từ khi chúng tôi làm việc với các phím, không có cách nào có thể để mysql tiêm, kể từ khi tôi biết các phím i xác định/chấp nhận bằng tay.

tưởng tượng dữ liệu này:

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

bạn đã định nghĩa phương pháp 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,","); 
} 

thì người xây dựng mảng truy vấn bind (tôi có thể sử dụng tài liệu tham khảo mảng trực tiếp nhưng cho phép đơn giản hóa):

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

thì bạn thực hiện ...

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

Bạn cũng có thể đi cho một bản cập nhật dễ dàng với ...

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

Nhưng phần quan trọng nhất ở đây là chức năng serialize_type

-1

Hãy thử điều này

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

Bạn nên mô tả điều này hoạt động khác hoặc tốt hơn so với các câu trả lời khác. Vì nó là viết tắt của "Hãy thử điều này" là khá vô ích. – Eiko