Как запросить таблицу на основе до 17 различных переменных?

#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); 
}
  

Это требует от вас:

  1. Переименуйте ваши параметры в точные названия столбцов
  2. Соберите все данные в массив вместо отдельных переменных Кстати, похоже, что вы не проверяете переменные параметров для SQL-инъекции. Если они отправлены пользователем, вы должны.
  3. Выполняйте все свои сравнения, используя «LIKE». Если это проблема, вы можете создать пару специальных случаев, чтобы позаботиться о параметрах «LIKE».

Предполагая, что вы готовы внести эти изменения, это намного чище.

Кстати, вы спрашиваете о PHP, но ваш код выглядит как C #. Что дает?

Комментарии:

1. Ни один из входных данных еще не очищен, но они будут, спасибо 🙂 Что касается первого фрагмента — он был основан на фрагменте, который я нашел здесь, но я не распознал как PHP. Прежде чем я отредактировал вопрос, я спросил, был ли это вообще PHP. Никто не возвращался к этому, поэтому я разработал его так, как если бы это было. Я до сих пор на самом деле не знаю, так это или нет. Поиск в Google возвращает ответы C #…

2. Я могу следовать синтаксису запроса Saggi, но меня немного смущает ваш (моя вина, не ваша!). Для меня это продвинутый материал! Я больше не перечисляю параметры?

3. @Eamonn: Это не PHP, это точно. В PHP переменные начинаются с «$». В любом случае, чтобы воспользоваться моим предложением, вы должны собрать данные в массив, подобный этому: $params[«ProfileName»]=»John»; Как вы можете видеть, ключ массива совпадает с именем столбца. Таким образом, вместо перечисления всех столбцов, вы можете просто выполнить цикл по массиву и получить как значение, так и имя столбца. Тем не менее, если вы найдете другой ответ более понятным, это то, что вам следует использовать. В противном случае у вас возникнут проблемы с последующей поддержкой вашего кода.

4. Отлично, спасибо, я еще раз упомяну это, когда узнаю больше 🙂