2017-01-19 67 views
2

我有一個從get檢索的關聯數組,我想用數組中的數據生成sql查詢字符串的「where子句」。如何從GET生成SQL查詢

$get_array = ['title'=>'abc', 'author'=>'John'] 

我創建了一個模板陣列具有不同的字符串不同的字段名稱,然後循環它通過get陣列產生的條款陣列:

$tpl = ['title' => 'title LIKE ?', 
     'author' => 'author LIKE ?', 
     ]; 

$where_clause_array = []; 
$binding_array = []; 

foreach ($get_array as $field_name => $field_value){ 
    foreach ($tpl as $table_field_title => $tpl_string) { 
    if ($field_name == $table_field_title) { 
     $where_clause_array[] = $tpl_string; 
     $binding_array[] = $field_value; 
    } 
    } 
} 

$clause_string = implode(' AND ', $where_clause_array); 

因此,我會得到一個字符串像「標題喜歡?和作者喜歡?」。但我的問題是,我有一個條款串取兩個值,而不是一個:

'year_start=>2000', 'year_end=>2017' 
'year BETWEEN ? AND ?' 

我無法弄清楚如何將這個進入循環。

+0

你是什麼意思「,但我的問題是,我有一個條款字符串需要兩個值而不是一個:「 – Beginner

+0

我的循環只接受get_array中的一個元素,並且每次只附加一個字符串,但其中一個字符串需要2個元素,但不會與循環一起使用。 – reddy

回答

1

在我們找到解決方案之前,我想指出,您不需要嵌套的foreach語句。你只能通過在模板上的所有按鍵一次,每次需要循環,所以下面的代碼會得到相同的結果,你目前有:

foreach ($tpl as $table_field_title => $tpl_string) { 
    if (array_key_exists($table_field_title, $get_array)) { 
     $where_clause_array[] = $tpl_string; 
     $binding_array[] = $get_array[$table_field_title]; 
    } 
} 

大廈這一點,我們只需要讓你做的如果您有任何給定參數的多個值,則在每次迭代中多次插入$binding_array

因此,這將做的工作:

foreach ($tpl as $table_field_title => $tpl_string) { 
    if (array_key_exists($table_field_title, $get_array)) { 
     $where_clause_array[] = $tpl_string; 

     $field_value = $get_array[$table_field_title]; 

     if (gettype($field_value) != 'array') $field_value = Array($field_value); 

     foreach ($field_value as $value) { 
      $binding_array[] = $value; 
     } 
    } 
} 

你只需要調整您的模板:

$tpl = array('title' => 'title LIKE ?', 'author' => 'author LIKE ?', 'dates' => 'year BETWEEN ? AND ?'); 

和輸入數據:

$get_array = array('title' => 'abc', 'author' => 'John', 'dates' => array('2000', '2017')); 

的最終結果將是像這樣:

$clause_string = implode(' AND ', $where_clause_array); 
echo $clause_string . '<br>'; 
var_dump($binding_array); 

// title LIKE ? AND author LIKE ? AND year BETWEEN ? AND ? 
// array(4) { [0]=> string(3) "abc" [1]=> string(4) "John" [2]=> string(4) "2000" [3]=> string(4) "2017" } 
+0

謝謝,它的工作原理。很好解釋。 – reddy

+0

太棒了!很高興它幫助..! – BizzyBob

0

由於您嘗試抽象查詢構建的方式,同時仍使用GET參數的非標準化字段名稱,因此不需要使用BETWEEN,使用年份> = =更簡單。子句和另一年< =?條款分開。另外,如果要抽象查詢構建,則不必爲每個字段定義模板,只需選擇一個默認運算符(例如LIKE一個)並將其他所有內容視爲覆蓋。

下面是一個代碼示例中,我爲你準備的,讓你使用PARAMS你同時讓你只擔心定義覆蓋的GET(即不規範的行爲),以確保:

<?php 
$get_array = [ 
    'title' => 'abc', 
    'author' => 'John', 
    'year_start' => '2000' 
    'year_end' => '2017' 
]; 

$overrides = [ 
    'year_start' => ['column' => 'year', 'operator' => '>='], 
    'year_end' => ['column' => 'year', 'operator' => '<='] 
]; 

$where_clause_array = []; 
$binding_array = []; 

foreach ($get_array as $field_name => $field_value){ 
    if(isset($overrides[$field_name])){ 
     $override = (object) $overrides[$field_name]; // Use an object as its syntax for accessing properties is shorter than array (e.g. $object->property vs $object['property']) 
     $column = $override->column ?: $field_name; // If override has a column name use it, otherwise ues the field name in the GET params 
     $where_clause_array[] = "{$column} {$override->operator} ?"; 
    } 
    else{ 
     $where_clause_array[] = "{$field_name} LIKE ?"; // We use LIKE as default operator, but we could use = instead and just LIKE in the overrides instead 
    } 

    $binding_array[] = $field_value; 
} 

$clause_string = implode(' AND ', $where_clause_array); 

希望能幫助到你。如果確實如此,請將回答的問題標記出來,如果您還有其他問題,請告訴我,我很樂意提供幫助。

0

您可以使用array_walk函數。

請嘗試下面的代碼在所有條件下能獲得查詢(即:如果year_start或year_end爲null):

$test_array = ['title'=>'abc', 'author'=>'John', 'year_start'=>2000, 'year_end'=>2017]; 
$tpl = array(); 
array_walk($test_array, function(&$a, $b) use (&$tpl,&$test_array) { 
if($b == 'year_start' || $b == 'year_end'){ 
    if($b == 'year_start' && $a){ 
     if($test_array['year_end'] != NULL){ 
      $tpl['dates'] = 'year BETWEEN ? AND ?'; 
     }else{ 
      $tpl['dates'] = 'year > ?'; 
     } 
    } 
    if($b == 'year_end' && $a && !isset($tpl['dates'])){ 
     $tpl['dates'] = 'year < ?'; 
    } 
}else{ 
    $tpl[$b] = "$b LIKE ?"; 
} 
}); 

print_r($tpl);