如何从GET生成SQL查询

时间:2017-01-19 03:09:34

标签: php get

我有一个从get检索的关联数组,我想使用数组中的数据生成sql查询字符串的“where子句”。

$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 ?'

我无法弄清楚如何将它放入循环中。

3 个答案:

答案 0 :(得分: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" }

答案 1 :(得分:0)

您不需要使用BETWEEN,因为您在尝试抽象查询构建的同时仍然使用GET参数的非规范化字段名称,它使用起来更简单一年&gt; =?条款和另一年&lt; =?条款分开。

此外,如果您要抽象查询构建,则不必为每个字段定义模板,只需选择默认运算符(例如LIKE),并将其他所有内容视为覆盖

这里是我为您准备的代码示例,它允许您继续使用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);

希望它有所帮助。如果确实如此,请标记已回答的问题,如果您有任何其他问题,请与我们联系。我很乐意为您提供帮助。

答案 2 :(得分: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);