Не знал как назвать тему, поэтому у темы корявое название. Я хотел рассказать тут о двух проблемах с которыми я столкнулся, и самые оптимальные пути их решения, которые я нашёл. Довольно частое явление, когда при в форме создаётся два селекта и при выборе в одном должны выбраться определённые данные в другом. У меня была задача такого плана: есть марки машин и модели каждой марки. Подгружать все модели и марки сразу нет смысла, т.к. страница будет требовать изрядно ресурсов. Я поступил так: создал в базе таблицу auto. ------------------------------------------------------------ id | pid | name ------------------------------------------------------------ затем создал скрипт чтобы записывать марки. В итоге у меня получилось что-то такое ------------------------------------------------------------ id | pid | name ------------------------------------------------------------ 1 |0 | Audi 2 |0 | BMW 3 |0 | Dodge 4 |0 | Ford 5 |0 | Jaguar Затем я записал модели, линкуя их на марку через параметр pid ------------------------------------------------------------ id | pid | name ------------------------------------------------------------ 1 |0 | Audi 2 |0 | BMW 3 |0 | Dodge 4 |0 | Ford 5 |0 | Jaguar 6 |1 | 80 7 |1 | 100 8 |2 | X6 ... Сделать это довольно просто. Затем я создал такую страничку с элементами: 1) select и в него записал все строки с pid=0 (т.е. марки) Code: <select id="marka" name="marka"> <option onclick="getmodel(this)" value="1">Audi</option> <option onclick="getmodel(this)" value="2">BMW</option> <option onclick="getmodel(this)" value="3">Dodge</option> <option onclick="getmodel(this)" value="4">Ford</option> <option onclick="getmodel(this)" value="5">Jaguar</option> </select> 2) пустой select для моделей Code: <select id="marka" name="marka"> </select> Ajax я плохо знаю, поэтому где-то на ачате давно брал скрипт для работы с ajax. Вот сами скрипты на странице: Code: var model = document.getElementById("model"); function none() { }; function request_model(url) { var r; if (window.XMLHttpRequest) { r = new XMLHttpRequest(); r.onreadystatechange = none; r.open("GET", url, false); r.send(null); } else if (window.ActiveXObject) { r = new ActiveXObject("Microsoft.XMLHTTP"); if (!r) r = new ActiveXObject("Msxml2.XMLHTTP"); if (r) { r.onreadystatechange = none; r.open("GET", url, false); r.send(null); } } if (r.responseText!="") { eval(r.responseText); } } function addOption(oListbox, text, value) { var oOption = document.createElement("option"); oOption.appendChild(document.createTextNode(text)); oOption.setAttribute("value", value); oListbox.appendChild(oOption); } function getmodel(item) { while (model.options.length) { model.options[0] = null; } if (document.getElementById("marka").selectedIndex!=0) { request_model('/getmodel.php?marka='+item.value); } } Вооот, остался только скрипт для извлечения моделей(getmodel.php): Code: if (isset($_GET['marka'])) { $db = new DB(); $db->dbquery("SELECT * FROM avto WHERE pid='".$db->secure($_GET['marka'])."'".$s); $res = $db->getresult(); if ($res !== false) { while ($row = mysql_fetch_row($res)) { echo 'addOption(model, "'.$row[2].'", "'.$row[0].'");'; } } } } P.S. у меня написан класс для работы с бд, но вообщем-то понятно как и что там. Собственно это и всё вроде. Я один раз написал и теперь просто видоизменяю, и согласен что немного коряво написано, но нужно было просто придумать как можно быстрее рабочую версию. Вторая проблема с которой я столкнулся была чем-то похожа с первой. У меня в форме было очень много параметров и я не знал как извратиться чтобы написать поменьше кода. Приведу пример для одного select'а для выбора кузова Code: <select name="kuzov" <option value="1">Бортовой грузовик</option> <option value="2">Внедорожник</option> <option value="3">Кабриолет</option><option value="4">Купе</option> <option value="5">Лимузин</option> <option value="6">Микроавтобус</option> <option value="7">Минивэн</option> <option value="8">Пикап</option> <option value="9">Седан</option> <option value="10">Универсал</option> <option value="11">Фургон</option> <option value="12">Хэтчбек</option> <option value="13">Грузовик</option> </select> Мало того что надо было выводить в итоге название кузова, так ещё и выборку по нему нужно было делать. В итоге просто создавать кучу селектов было нелогично, т.к. потом меня бы конкретно бы это ограничило. И я снова вспомнил свой способ при работе с марками. Я создал таблицу parent ------------------------------------------------------------ id | name ------------------------------------------------------------ 1 | kuzov 2 | toplivo 3 | strana ... и создал таблицу param ------------------------------------------------------------ id | name | parent ------------------------------------------------------------ 1 | Бортовой грузовик | 1 2 | Внедорожник | 1 .... В итоге создав функцию для заполнения селекта Code: function getselnames($selname) { $db = new DB(); $db->dbquery("SELECT * FROM parent WHERE name='".$db->secure($selname)."'"); $result=$db->getstring(); if ($result!==false) { $db->dbquery("SELECT * FROM param WHERE parent='".$result[0]."'"); $result=$db->getresult(); if ($result!==false) { while ($row = mysql_fetch_row($result)) { echo '<option value="'.$row[0].'">'.$row[1].'</option>'; } } } } Я заполнял селекты тремя строчками Code: <select name="kuzov"> <?php getselnames('kuzov');?> </select> что есть очень удобно. Затем у меня решилась куча проблем, и наверняка даже те, о которых я не подозреваю до сих пор. В итоге выборка приобрела такой вид: Code: if (isset($_GET['kuzov'])) {//проверка на то что селект есть в пост $res = mysql_query("SELECT * FROM param where parent=1 and id='".mysql_real_escape_string($_GET['kuzov'])."'"); if (mysql_num_rows($res)) $where.=" and kuzov='".$db->secure($_GET['kuzov'])."'"; } } .....//таким образом проверяются все select'ы $adv = mysql_query("SELECT * FROM adv where 1".$where);//собственно выборка объяв, которая мне нужна была Коды немного сыровты, но цель была показать саму идею. P.S. тема была названа извлечение подкатегорий, т.к. таблица avto называлась category
1) в select можно обойтись одним аттрибутом onChange, вместо десятка onClick 2) в пункте два можно обойтись одним селектом и/или избавиться от первой базы 3) в последнем блоке кода совсем не понятно откуда и зачем это взялось 4) лучше не использовать select * from, а перечислять требуемые столбцы 5) хотелось бы услышать, какие и как следует в данном случае ставить индексы на таблицу
1) согласен) 2) насчёт одного селекта что-то не понял. А насчёт того чтобы обойтись без первой таблицы, как я понял parent, несоглашусь, т.к. форм много, а заполняешь ты их из админки, т.к. в любой момент надо чтото удалить/добавить. Можно оставить цифры конечно(типа для кузова 1, для топилва 2 и т.д.), но ты её заполнить просто не сможешь, сам подумай. 3) последний щас распишу) на самом деле не понятно 4) согласен 5) напишу
Seravin 2) Как-то так. При этом не теряем время на отправку/обработку нового запроса Code: SELECT b.name as param_name FROM parent a LEFT JOIN param b ON a.id=b.parent WHERE a.name='kuzov' А избавиться - аналогично как и в первом все собрать в одну таблицу 3) Все равно как-то мутно, не могу сформулировать но у меня какой то внутренний протест против такого кода
3) )))) это то к чему пришёл я) одна голова хорошо а 15 лучше, естественно что всё это можно отточить, но я не мог особо на деталях зацикливаться. Когда буду всё оптимизировать, тогда уже и буду исправлять. 2) насчёт этого вообщем то в 3) ответ