PHP и MYSQL: создание запроса на основе нескольких входных значений от пользователей

Гипотетически у меня три таблицы: * recipes — содержит рецепты * ингредиенты — список предметов * блюда — список блюд

У меня есть форма, которая генерирует выбор, например:

Choose what ingredients you have:
- apples
- bananas 
- cherries

Choose the meal this is for:
- breakfast
- lunch
- dinner

Я хочу, чтобы пользователь мог выбирать из вышеперечисленного или ни из одного, т. е. он мог выбрать яблоки ИЛИ вишни ИЛИ (бананы и обед)

Когда я запрашиваю MySQL, мой запрос примерно

select recipes.* from recipes

or

select recipes.* from recipes, ingredients 
where recipes.id= ingredients.id and ingredients.list in ('apple');

or

select recipes.* 
from recipes, ingredients, meal 
where recipes.id= ingredients.id 
      and ingredients.list 
      and ingredients.id = meals.id 
      and ingredients.list ('apple') 
      and meals.list in ('lunch');

Есть ли хороший способ сказать (в PHP), если этот массив существует (т.е. is_array(ингредиенты) добавить в запрос таблицу (ингредиенты) и в конце добавить (".ingredients.list в ("яблоко")). ..

без необходимости записывать все возможные комбинации или возможные входные данные (т. е. выбранные пользователем из списка ингредиентов, или из списка ингредиентов и блюд, или из списков)?


person Ryank    schedule 04.09.2010    source источник
comment
+1 за красиво оформленный вопрос, особенно для нового пользователя! По сути, вам нужны «критерии поиска» - чтобы вытащить все рецепты с яблоками и все рецепты обедов с бананами и т. Д.?   -  person Will A    schedule 04.09.2010
comment
Рассматривали ли вы возможность использования ORM? Это позволит вам создать динамический запрос с минимальными усилиями.   -  person DrColossos    schedule 04.09.2010
comment
не так красиво. на самом деле трудно читать очень длинную строку   -  person Your Common Sense    schedule 04.09.2010


Ответы (3)


Есть несколько подходов к решению этой проблемы.

Если вы хотите узнать, существует ли ключ в массиве, вы можете использовать array_key_exists

person Shamim Hafiz    schedule 04.09.2010
comment
Мне не нужно знать, выходит ли ключ, просто есть ли массив, и если массив есть, измените строку запроса. - person Ryank; 05.09.2010

Вы должны создать два массива для возможных таблиц и кусков, а затем сделать запрос, который собирает все:

$wheres=array();
$tables=array();
if(isset($_POST['ingredients'])) {
  $tables[]='ingredients';

  $ingredients=array_map('mysqL_real_escape_string', $_POST['ingredients']);
  $wheres[]='ingredients.list IN (\''. join(', ', $ingredients). '\')';
  //add other wheres if you want
}
if(isset($_POST['meals'])) {
  $tables[]='meal';

  $meals=array_map('mysqL_real_escape_string', $_POST['meals']);
  $wheres[]='meals.list IN (\''. join(', ', $ingredients). '\')';
  //add other wheres if you want
}

if(!$tables) {
  echo 'You have not chose anything!';
} else {
  $query = 'SELECT * FROM '. join(',', $tables). ' WHERE '. join(' AND ', $wheres);
  //do other stuff..
}
person aularon    schedule 04.09.2010
comment
Это круто, но это плохо масштабируется, скажем, я потенциально мог бы вернуть 5 массивов, которые изменили бы запрос... - person Ryank; 05.09.2010
comment
в этом случае создайте массив, в котором ключи являются допустимыми входными переменными $_POST и имеют каждое из их значений: 'meals' => array('table'=>'meal', 'fieldname'=>'meals'), например. и с помощью небольшого простого цикла вы зацикливаете этот массив и создаете свой запрос. как только вы захотите изменить, вы добавите новый элемент в этот массив. разве это не круче :) - person aularon; 06.09.2010

Я не вижу здесь "всех возможных комбинаций или возможных входных данных", а просто все возможные входные данные.
Я бы проверил все возможные входные данные и добавил их в запрос, если они заполнены.

person Your Common Sense    schedule 04.09.2010
comment
Я думаю, что мог бы использовать sprintf() и изменить его, но я надеялся на более масштабируемое и элегантное решение. - person Ryank; 05.09.2010
comment
@Ryank попробуйте свои 5 новых массивов, и вы увидите, что это невозможно сделать автоматически. Каждый параметр требует своей обработки. Не каждое условие можно записать как простую проверку на равенство, но другие могут использовать between, less than, greater than, like и тому подобное. Элегантно предопределить все ваши условия. Не прогнозируйте будущее использование на основе такого глупого примера. Сначала попробуйте ИСПОЛЬЗОВАТЬ этот более сложный вопрос. И только потом искать решение - person Your Common Sense; 05.09.2010