Как создать запрос SQL из GET

У меня есть связанный массив, полученный из get, и я хотел сгенерировать «предложение where» строки запроса 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);

В результате я получу строку типа «title LIKE? AND author LIKE?». Но проблема в том, что у меня есть строка предложения, которая принимает два значения вместо одного:

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

Я не мог понять, как поместить это в цикл.

2

Решение

Прежде чем мы перейдем к моему решению, я хочу отметить, что вам не нужны вложенные 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

Другие решения

Вам не нужно использовать BETWEEN. Из-за того, как вы пытаетесь абстрагировать построение запроса, все еще используя ненормализованные имена полей для параметров GET, проще использовать год> =? пункт и еще один год <знак равно пункт отдельно.

Кроме того, если вы собираетесь абстрагировать построение запроса, вам не нужно определять шаблон для каждого поля, просто выберите оператор по умолчанию (например, 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);

Надеюсь, поможет. Если это так, отметьте ответ на вопрос и дайте мне знать, если у вас есть дополнительные вопросы, я с радостью помогу.

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);
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector