#php #mysql #dynamic
#php #mysql #динамический
Вопрос:
У меня есть таблица MySQL, в которой я хочу выполнить поиск через размещенную форму. Проблема в том, что существует около 17 переменных, которые конечный пользователь может захотеть запросить по отдельности или в комбинации. Это приводит к слишком большому количеству возможностей для операторов else-if. После запроса здесь я создал следующий запрос:
$query = "SELECT * FROM profiles";
$postParameters = array("name","height","gender","class","death","appro","born","tobiano","modifier","adult","birth","sire","dam","breeder","owner","breed","location");
$whereClause = " WHERE 1 = 1";
foreach ($postParameters as $param) {
if (isset($_POST[$param]) amp;amp; !empty($_POST[$param])) {
switch ($param) {
case "name":
$whereClause .= " AND ProfileName='".$_POST[$param]."' ";
break;
case "height":
$whereClause .= " AND ProfileHeight='".$_POST[$param]."' ";
break;
case "gender":
$whereClause .= " AND ProfileGenderID='".$_POST[$param]."' ";
break;
case "class":
$whereClause .= " AND ProfileBreedClassID='".$_POST[$param]."' ";
break;
case "death":
$whereClause .= " AND ProfileYearOfDeath='".$_POST[$param]."' ";
break;
case "appro":
$whereClause .= " AND ProfileYearApproved='".$_POST[$param]."' ";
break;
case "born":
$whereClause .= " AND ProfileYearOfBirth='".$_POST[$param]."' ";
break;
case "tobiano":
$whereClause .= " AND ProfileTobianoTest='".$_POST[$param]."' ";
break;
case "modifier":
$whereClause .= " AND ProfileColourModifier='".$_POST[$param]."' ";
break;
case "adult":
$whereClause .= " AND ProfileAdultColourID='".$_POST[$param]."' ";
break;
case "birth":
$whereClause .= " AND ProfileBirthColourID='".$_POST[$param]."' ";
break;
case "sire":
$whereClause .= " AND ProfileSireReg='".$_POST[$param]."' ";
break;
case "dam":
$whereClause .= " AND ProfileDamReg='".$_POST[$param]."' ";
break;
case "breeder":
$whereClause .= " AND ProfileBreederID='".$_POST[$param]."' ";
break;
case "owner":
$whereClause .= " AND ProfileOwnerID='".$_POST[$param]."' ";
break;
case "breed":
$whereClause .= " AND ProfileBreedID='".$_POST[$param]."' ";
break;
case "location":
$whereClause .= " AND ProfileLocationCountryID='".$_POST[$param]."' ";
break;
}
}
}
$query .= $whereClause;
$result = mysql_query("$query");
while ($row = mysql_fetch_array($result)) {
echo $row['ProfileName'] . '<br/>';
}
Спасибо Сагги Малахи за этот метод!
Ответ №1:
Лучшим подходом было бы определить массив со всеми возможными параметрами POST, а затем выполнить над ними обработку при создании вашего предложения WHERE с использованием оператора PHP switch.
<?php
$postParameters = array("name","height","gender");
$whereClause = " WHERE 1 = 1";
foreach ($postParameters as $param) {
if (isset($_POST[$param]) amp;amp; !empty($_POST[$param])) {
switch ($param) {
case "name":
$whereClause .= " AND ProfileName='".$_POST[$param]."' ";
break;
case "height":
$whereClause .= " AND ProfileHeight='".$_POST[$param]."' ";
break;
// more cases....
}
}
}
$query .= $whereClause;
Комментарии:
1. И как мне сформулировать этот окончательный запрос? $result = mysql_query($query);?
2. @Eamonn Да, ваши изменения в строке isset верны. исправлен мой ответ.
3. @Eamonn да, используйте mysql_query. смотрите php.net/manual/en/function.mysql-query.php для примеров.
4. @Saggi Malachi — Спасибо, Сагги! Должна ли версия вашего скрипта, которую я опубликовал в своем вопросе, сейчас не работать? Я получаю ошибку «недопустимый аргумент …» (в частности, в while ($row = mysql_fetch_array ($ result)) {строка)
5. Замените mysql_query(‘$query’); на mysql_query(«$query»); (Вы должны использовать двойные кавычки в PHP для анализа переменных, содержащихся в ваших строках)
Ответ №2:
Другой способ, немного более гибкий.
<?php
// Use $ to indicate variable name, $ will be stripped when getting data from $_POST.
// The $variable will then be replaced with the data from the form.
// This way you setup the entire condition in the array, more flexible.
$set_data = array(
'ProfileHeight >= $height',
'ProfileGenderID = $gender',
'ProfileTobianoTest LIKE %$tobiano%',
'ProfileOwnerID = $owner',
);
$where = '';
foreach ($set_data as $str) {
// Get variable name from str.
if (!preg_match('/$([a-zA-Z0-9_] )/', $str, $matches))
die('Invalid settings.');
$name = $matches[1];
if (!isset($_POST[$name]))
continue;
$data = trim($_POST[$name]);
if ($where != '')
$where .= ' AND ';
$where .= str_replace('$' . $name, mysql_real_escape_string($data), $str);
}
if ($where != '') {
$query = 'SELECT * FROM profiles WHERE ' . $where;
print "$queryn";
}
Комментарии:
1. О, вау, это выглядит эффективно — я собираюсь попробовать… Спасибо, Йохан!
Ответ №3:
Верхняя, похоже, будет работать должным образом.
Вы их тестировали?
Хотя в первом была опечатка: ‘ProdileHeight’ должно быть ‘ProfileHeight’, я полагаю
Комментарии:
1. И вы, возможно, захотите добавить пробел после кавычек:
" AND ProfileHeight LIKE..."
2. При использовании первого метода, нужно ли мне сначала размещать значения формы? Я привык иметь список: $name = $_POST[‘имя’], $height = $ _POST [‘высота’] и т.д… Нормально ли просто указывать «необработанные» имена в запросе: ГДЕ ProfileGenderID = ‘gender’?
3. Кроме того, как передать это в запросе? $result = mysql_query(строковый запрос); ?
4. Я бы тоже использовал список, таким образом, вы ссылаетесь на данные формы только один раз. Попробуйте этот запрос, в противном случае попробуйте $query вместо запроса string. php сначала распечатает запрос, чтобы убедиться, что он скомпилирован правильно. Итак, попробуйте напечатать строковый запрос; и вывести $query; и посмотреть, какой из них печатает SQL (так что делайте по одному за раз) Затем используйте эту в $result
Ответ №4:
Если вы готовы внести несколько изменений:
$query = "SELECT * FROM profiles";
$parameters = "";
foreach ($params as $param => $value)
{
// Important! validate the content of $value to avoid SQL injections
if (!empty(param))
{
$parameters .= "AND $param LIKE '%" . $value . "%' ";
}
}
if (!empty($parameters))
{
$parameters = preg_replace("/^AND/", "WHERE", $parameters, 1);
}
Это требует от вас:
- Переименуйте ваши параметры в точные названия столбцов
- Соберите все данные в массив вместо отдельных переменных Кстати, похоже, что вы не проверяете переменные параметров для SQL-инъекции. Если они отправлены пользователем, вы должны.
- Выполняйте все свои сравнения, используя «LIKE». Если это проблема, вы можете создать пару специальных случаев, чтобы позаботиться о параметрах «LIKE».
Предполагая, что вы готовы внести эти изменения, это намного чище.
Кстати, вы спрашиваете о PHP, но ваш код выглядит как C #. Что дает?
Комментарии:
1. Ни один из входных данных еще не очищен, но они будут, спасибо 🙂 Что касается первого фрагмента — он был основан на фрагменте, который я нашел здесь, но я не распознал как PHP. Прежде чем я отредактировал вопрос, я спросил, был ли это вообще PHP. Никто не возвращался к этому, поэтому я разработал его так, как если бы это было. Я до сих пор на самом деле не знаю, так это или нет. Поиск в Google возвращает ответы C #…
2. Я могу следовать синтаксису запроса Saggi, но меня немного смущает ваш (моя вина, не ваша!). Для меня это продвинутый материал! Я больше не перечисляю параметры?
3. @Eamonn: Это не PHP, это точно. В PHP переменные начинаются с «$». В любом случае, чтобы воспользоваться моим предложением, вы должны собрать данные в массив, подобный этому: $params[«ProfileName»]=»John»; Как вы можете видеть, ключ массива совпадает с именем столбца. Таким образом, вместо перечисления всех столбцов, вы можете просто выполнить цикл по массиву и получить как значение, так и имя столбца. Тем не менее, если вы найдете другой ответ более понятным, это то, что вам следует использовать. В противном случае у вас возникнут проблемы с последующей поддержкой вашего кода.
4. Отлично, спасибо, я еще раз упомяну это, когда узнаю больше 🙂