Как реализовать каскадные раскрывающиеся списки в PHP и AJAX?

Мне нужна серьезная помощь или совет по тому, что я потратил бесчисленное количество часов на исследование и ничего не нашел.

У меня есть проект, в котором мне нужно извлечь данные из базы данных MDB с помощью PHP. Мне удалось подключиться к базе данных, я могу запрашивать базу данных и отображать результаты в таблице, и я даже могу выполнять поиск в базе данных с помощью ввода текста.

Моему клиенту нужна расширенная функция поиска с несколькими раскрывающимися списками. Эти раскрывающиеся списки получают значения из базы данных. Все это еще хорошо. Я могу заполнить выпадающие списки из базы данных.

База данных представляет собой базу данных транспортных средств (идентификатор, инвентарный номер, марка, модель, год, цена, характеристики и т. д.). К сожалению, все данные о транспортном средстве находятся в одной таблице. Так, например, в базе есть четыре автомобиля ASTON MARTIN, каждый со своим ID и моделью.

Я знаю, что было бы лучше иметь как минимум две отдельные таблицы: марка и модель. Но база данных создается сторонним приложением, которое сохраняет копию базы данных на сервере, к которому я подключаюсь.

Вопрос в том, можно ли с помощью PHP и AJAX иметь каскадные выпадающие списки при рисовании данных из одной и той же таблицы? Так, например, если я выберу ASTON MARTIN из списка Make, во втором раскрывающемся списке будут показаны только модели, относящиеся к ASTON MARTIN?

См. приведенную ниже попытку попробовать это... Этот сценарий успешно загружает столбец Make из базы данных в первый раскрывающийся список и столбец Modal из базы данных во второй раскрывающийся список, но они не связаны. В настоящее время первый вариант — ASTON MARTIN, а соответствующая ему модель — CORSA (это совсем не правильно).

     <script type="text/javascript">

          function loadXMLDoc() {
          var xmlhttp;
           if (window.XMLHttpRequest) {
           // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
       } else {// code for IE6, IE5
           xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
       }

         xmlhttp.onreadystatechange=function() {
     if (xmlhttp.readyState==4 && xmlhttp.status==200) {
         document.frm.modelSelection.innerHTML=xmlhttp.responseText;
           }
       }

        var makevalue=document.frm.makeSelection.value;

        xmlhttp.open("GET","?ajaxmake="+makevalue,true);
        xmlhttp.send();
            }

            </script>

            <?php 

            $dbName = "C:/xampp/htdocs/new/db/savvyautoweb.mdb";

            // Throws an error if the database cannot be found
            if (!file_exists($dbName)) {
            die("Could not find database file.");
            }

            // Connects to the database
            // Assumes there is no username or password
            $conn = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", '', '');

            ?>

            <form action="" method="post" name="frm">
        <select name="makeSelection" onchange="loadXMLDoc()">

            <?php
         $resultMake = odbc_exec($conn, "SELECT Make FROM Vehicle ORDER BY Make") or die (odbc_errormsg());
         while ($rowMake = odbc_fetch_array($resultMake)) {
     echo "<option value='$rowMake[Make]'>$rowMake[Make]</option>";
         }
              ?>
           </select>
           <select name="modelSelection">

            <?php
        if (isset($_REQUEST['ajaxmake'])) {
        $resultModel = odbc_exec($conn, "SELECT Model FROM Vehicle") or die (odbc_errormsg());

         while ($rowModel = odbc_fetch_array($resultModel)) {
           echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
         }

         die();
             }
                 ?>
             </select>
             <input type="submit" name="submit" value="Go">
                 </form>

РЕДАКТИРОВАТЬ приведенный выше код на основе вашего решения. Спасибо тебе за это.

Кажется, что функция работает, но она заполняет второй раскрывающийся список столбцом make, а не столбцом модели. Есть идеи, почему?

Спасибо, Деон Джонкер.


person Deon    schedule 13.02.2014    source источник


Ответы (1)


Для вашего выбора вы можете добавить атрибут onchange, подобный этому

<select name="makeselection" onchange="filtermodelselection()">

Вы добавляете функцию filtermodelselection(), которая считывает выбранный параметр из вашего makeselection, например (дайте имя вашей форме или идентификатор для вашего выбора, теперь я буду использовать «frm» как имя формы)

var makeid=document.frm.makeselection.value;

Вы отправляете свой ajax-запрос на страницу. затем с помощью makeid вы можете сделать запрос ajax на сервер следующим образом: http://www.w3schools.com/ajax/tryit.asp?filename=tryajax_get_unique

function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.frm.modelSelection.innerHTML=xmlhttp.responseText;
    }
  }
var makevalue=document.frm.makeSelection.value;
xmlhttp.open("GET","?ajaxmake="+makevalue,true);
xmlhttp.send();
}

На стороне сервера вы получаете переменную $_REQUEST['ajaxmake'].

if (isset($_REQUEST['ajaxmake'])) {
   //do the magic the query, and then echo like what you did here:
while ($rowModel = odbc_fetch_array($resultModel)) {
    echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
}
//then die, to not echo anything else accidentally
die();
}

пример вывода:

<option value='AUDI'>AUDI</option>
<option value='BMW'>BMW</option>

на принимающей стороне с помощью ajax вы передаете полученное значение с сервера в innerHTML.like моделиSelection:

document.frm.modelselection.innerHTML=xmlhttp.responseText;

Если что-то непонятно, пожалуйста, не стесняйтесь спрашивать.

РЕДАКТИРОВАТЬ: поместите эту часть:

<?php
        if (isset($_REQUEST['ajaxmake'])) {
        $resultModel = odbc_exec($conn, "SELECT Model FROM Vehicle") or die (odbc_errormsg());

         while ($rowModel = odbc_fetch_array($resultModel)) {
           echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
         }

         die();
             }
   ?>

в начало файла. (конечно, после любых включений, кодов коннекторов базы данных)

person LaczkoUr    schedule 13.02.2014
comment
Спасибо за ответ. Так как же будет выглядеть функция filtermodelselection()? Я не совсем уверен, что вы подразумеваете под словом «На стороне сервера», вы делаете запрос, который фильтрует модели, а затем вы можете отправить параметры в виде строки с эхом? Я действительно зеленый, когда дело доходит до AJAX/Javascript. - person Deon; 13.02.2014
comment
Я обновил его для вас. забыл отредактировать onreadystatechange. держать на секунду - person LaczkoUr; 13.02.2014
comment
отредактировал onreadystatchange. Обратите внимание, что это не самое красивое решение, было бы лучше удалить параметры по одному, а затем добавить их по одному вместо этого дампа innerHTML. Но это было бы сложнее - person LaczkoUr; 13.02.2014
comment
Спасибо большое. Я внес некоторые коррективы в исходный вопрос. Кажется, что функция работает, но она заполняет второй раскрывающийся список столбцом «Модель» и столбцом «Изготовить». Любая идея, почему это произойдет? - person Deon; 13.02.2014
comment
Я не могу представить ситуацию. Во втором раскрывающемся списке перечислены модели и марки? - person LaczkoUr; 13.02.2014
comment
Вы должны проверить, является ли это вызовом ajax перед каждым другим выводом. Если вы этого не сделаете, это также будет сброшено в элемент select. Может быть, это проблема. - person LaczkoUr; 13.02.2014
comment
не могли бы вы написать свой sql-запрос? - person LaczkoUr; 13.02.2014
comment
Да, во втором раскрывающемся списке перечислены оба. - person Deon; 13.02.2014
comment
SQL-запрос выглядит следующим образом: - person Deon; 13.02.2014
comment
'Сделать': $resultMake = odbc_exec($conn, SELECT Make FROM Vehicle ORDER BY Make) или умереть (odbc_errormsg()); | 'Модель': $resultModel = odbc_exec($conn, SELECT Model FROM Vehicle) или умереть (odbc_errormsg()); - person Deon; 13.02.2014
comment
Единственная проблема может заключаться в том, что вы случайно сбросите их обоих. не могли бы вы обновить свой код в исходном сообщении, чтобы показать свой php/sql? Я мог сказать ошибку именно тогда - person LaczkoUr; 13.02.2014
comment
Сообщение обновлено ... Я не вижу, куда сбрасываются оба ... Я не уверен, где использовать пример вывода, который у вас есть в исходном ответе ... Я должен где-то его использовать? - person Deon; 13.02.2014
comment
Я обновил свой ответ, поместите свой код перед чем-либо еще. Другие части кода запускаются до обработки ajax, и в этом смысле это нехорошо. - person LaczkoUr; 13.02.2014
comment
Большое спасибо... Я попробую, когда вернусь в офис завтра утром... вы очень помогли... - person Deon; 13.02.2014
comment
Привет ... Спасибо за это ... Если я сделаю то, что вы предложили, раскрывающийся список «Модель» появится перед раскрывающимся списком «Сделать» ... он заполняет раскрывающийся список «Модель» только моделями из база данных... но она по-прежнему не связана с правильной маркой... поэтому, если я выберу Aston Martin в раскрывающемся списке "Марка", она все равно выдаст неправильную модель... - person Deon; 14.02.2014
comment
ВЫБЕРИТЕ модель ИЗ транспортного средства, перепишите этот запрос следующим образом: ВЫБЕРИТЕ модель ИЗ транспортного средства, ГДЕ Make = '.$_REQUEST['ajaxmake'].' - person LaczkoUr; 14.02.2014
comment
Привет, я сделал то, что вы предложили, переписав запрос. Что происходит сейчас, так это то, что он загружает правильные модели для выбранной марки, но также загружает все марки. Итак, если я выберу BMW, он загрузит все модели BMW, но также загрузит все марки. - person Deon; 17.02.2014
comment
Есть 2 случая. В первом случае производители находятся в верхней части списка. Это означает, что ваш php-код обработки ajax не запускается первым. В этом случае переместите свой код как можно выше. Во-вторых, если Makes являются последними вариантами, код не завершается после того, как вы повторите результаты. Убедитесь, что die(); находится в нужном месте - person LaczkoUr; 18.02.2014