Такая задача: есть файл с определёнными номерами деталей, в поле поиска вводится номер детали и ищу этот номер в файле. Но если номер вводимый пользователем отличается от того номера что содержится в файле, то естественно результат выдаст пустой. Но дело в том что запчасти бывают разных фирм и естественно имеют разные номера, пользователь не может знать по какой именно фирме находится у меня в наличии запчасть, поэтому номер может ввести одной фирмы а у меня эта деталь по другой фирме. Пример: 4a0407151 аналог 935716 аналог JTC254 ну и т.д. аналогов может быть много. На сколько понял это реализуется с помощью перекрёстных ссылок, т.е. какбы один номер равен другому, пользователь вводит любой из этих номеров а ему выдаёт то что есть в наличии. Хочу сделать как на http://exist.ua/, я знаю что там большая база номеров выдертая из программы, но мне не нужно столько номеров, мне достаточно их будет в ручную набить в файлик заменители эти. 1) как правильно составить файлик с аналогами? 4a0407151;935716;JTC254 - так нормально будет? 2) как привязать номера между собой? 4a0407151==935716==JTC254 -? 3) сам запрос на поиск результата strstr($number1, $number2) но с учётом перекрёстных ссылок в переменную $number1 получается надо подставлять каждый номер сюда? 4) или надо в бд заливать кроссы номеров и при выборке сравнивать? Вобщем направте меня пожалуйста.
вот что наваял.... Код (Text): $vhod = "4a0407151"; $crosse0 = "evr15"; $crosse1 = "15689"; $crosse2 = "89f6"; $crosse3 = "4a0407151"; $cross = array($crosse0, $crosse1, $crosse2, $crosse3); $v_faile = array("evr1","561","89f6","ERV5678"); foreach ($cross as $element){ if($vhod == $cross['0']||$vhod == $cross['1']||$vhod == $cross['2']||$vhod == $cross['3']){ foreach ($v_faile as $file_element){ $return = strstr($file_element, $element); echo $return; } } }; подправте пожалуйста
подправил чтоб искало вне зависимости от наличия пробелов точек... и.т.д. Код (Text): $vhod = "4a0.407 151"; $cross = array("evr15", "15689", "89f6", "4a0407151"); $v_faile = array("evr1","561","89kf6","evr15","ERV5678"); function normalize_number($data_corected) { return preg_replace("#\W#", "", $data_corected); }; function are_numbers_equal($number1, $number2) { return strstr(normalize_number($number1), normalize_number($number2)); } foreach ($cross as $element){ if(are_numbers_equal($vhod, $cross['0']) ||are_numbers_equal($vhod, $cross['1']) ||are_numbers_equal($vhod, $cross['2']) ||are_numbers_equal($vhod, $cross['3'])){ foreach ($v_faile as $file_element){ $return = are_numbers_equal($file_element, $element); echo '<pre>'; echo $return; echo '</pre>'; } } }; но не ищет если не дописать номер.. например написать не 4a0.407 151 а 4a0 407 15 я понимаю что получается что программе не с чем сравнивать, но бывают номера которые заканчиваются на 01C или B41 ... и народ не всегда это дописывает.
Если правильно понял, при указании одной детали, надо получить список всех имеющихся аналогов. Вникать в код не стал. Слишком сложно для моего времени суток. Но по теме могу предложить два варианта: 1. В файле - каждая строка "номер" детали, если для этой детали существуют аналоги, они все будут записаны в одной строке через определенный разделитель. При поиске просто находим строку с искомым номером, частью номера, результат explode() на найденной строке даст список всех аналогичных деталей. 2. База данных - Таблица "номера". В ней два поля "номер" и "тип детали". У "деталей - аналогов" тип будет одинаковым. Я далеко не мастер в построении запросов, и сделал бы, для начала, двумя: а. Находим деталь с LIKE в условии. (можно при этом и часть номера иметь и полный) б. Находим все детали с тем же типом. Мне вариант с базой ближе. Он гибче, проще поддается расширению и будет шустрее работать, но вносить данные придется сложнее чем в файл ручками.
та ничего сложного, файл сделать а потом загрузить его в базу. нормально. завтра буду думать над остальной частью
не понял насчёт полей... в каком поле что размещать... одному товару может соответствовать до 10 номеров аналогов.. наверное 10 полей надо делать.. или как?
Талица из двух полей: Поле 1: Номер, артикул или что там еще детали, например, "12345JPG" Поле 2: Тип детали, например 1, или "Фара", или "Бампер от Инфинити", что соответствует числу 523 Если у нас Бамперы к Инфинити производят 5 разных заводов и у каждого свой артикул, в базе будет 5 записей: 12346PG => 523 4321GH => 523 ЛяЛяЛя => 523 и т.д. В момент поиска, пользователь вводит, например, "321GH". результат "SELECT * FROM zapchasti WHERE artikul LIKE %321GH%" даст нам искомую юзером запись. Далее, имея тип из предыдущего запроса, "SELECT artikul FROM zapchasti WHERE type = 523" положит Вам на блюде все варианты бамперов к Инфинити, которые у Вас есть.
Топикстартер пишет про файл, но конечно эту работу удобнее доверить базе. Файл разве что для начальной загрузки справочника использовать. Есть код оригинальной детали, а есть аналоги. Мне кажется логичным и эффективным описывать узлы и детали прежде всего в оригинальных обозначениях. У записей про неоригинальные детали делать ссылку на id оригинальной детали. Оригинал ссылается сам на себя. Этот факт можно использовать для выбора "только оригинал". Очевидно выбор "все аналоги" это все записи с такой же ссылкой как у выбранной детали. Поиск по части названия через LIKE.
вот как сделал загрузку в бд, но не пойму как сделать не через switch... т.к. строчек в файле может быть около 2тысяч... в ручную писать case 2000: както неочень ))))))))))) Код (Text): foreach ($cross as $key => $elements){ foreach ($elements as $number){ } switch($key){ case 0: $key = 0; for($i = 0; $i<count($elements);$i++){ $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')"); } break; case 1: $key = 1; for($i = 0; $i<count($elements);$i++){ $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')"); } break; case 2: $key = 2; for($i = 0; $i<count($elements);$i++){ $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')"); } break; } }; нужно чтоб в $key записывалось число соответствующее новой строке... что-то не въеду никак как сделать. Код (Text): $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')"); Добавлено спустя 42 минуты: но как так сделать? не пойму структуру.. как записи будут выглядеть счас вот такого плана получается этот массив Код (Text): $cross = array( array("evr15", "15689", "89f6", "4a0407155"), array("889656", "3a540987.6"), array("1295.12-45", "LMI1845", "rufi2")); записывается в базу так Код (Text): number type_of_number evr15 0 15689 0 89f6 0 4a0407155 0 889656 1 3a540987.6 1 1295.12-45 2 LMI1845 2 rufi 2
люди подскажите, запутался окончательно поиск по базе данных идёт нормально Код (Text): $return = "89f6"; $v_faile = array("evr1","561","89kf6","evr15","ERV5678"); foreach($v_faile as $v_faile_num) { $price = mysql_query ("SELECT * FROM crossnumbers"); for ($i=0; $i<mysql_num_rows($price); $i++){ $value = mysql_fetch_assoc($price); if (are_numbers_equal($value[number], $return)) { //echo $value[number] . '<br>'; } } } } отбирает значения без проблем Код (Text): $pr = mysql_query ("SELECT number FROM crossnumbers WHERE type_of_number = 0"); for ($j=0; $j<mysql_num_rows($pr); $j++){ $va = mysql_fetch_assoc($pr); echo $va[number] . '<br>'; но как это связать друг с другом!!???
Я тоже не понял что есть что. foreach (... $key=>...) + switch($key) это откровенный говнокод. Давай договоримся что именно мы должны решить: * структуру базы или * формат файла загрузки или * написать скрипт начальной загрузки? Предлагаю обсудить эти вопросы отдельно и последовательно.
1) в бд есть таблица crossnumbers в ней 2 поля number и type_of_number 2) надо загрузить туда номера деталей с учётом связи между ними. делаю так как писал выше... вы сказали что это говнокод знаю.. но другое не придумал или я даже таблице не такую сделал?...... 3) а скрипт начальной загрузки это вы что имеете ввиду? скрипт который загрузит номера деталей в БД? ну да... я и пытаюсь его правильно сделать, а после надо чтоб ещё и поиск работал.. но до него ещё далеко..
Есть файл, организованный по принципу: Строка 1: Номер детали Строка 2: Номер детали ... Строка x: Номер детали,Номер аналога,Номер аналога Строка x+1: Номер детали ... Есть база с двумя полями, у Вас она уже есть. Загружаем файл в базу (псевдокод, который можно оптимизировать): Код (PHP): $f = file('имя файла с номерами'); for ($i = 0; $i < count($f); $i++) { $nums = explode($f[i], ','); foreach($nums as $num) { $type = $i + 1; mysql_query("INSERT INTO crossnumbers VALUES ('$num', '$type')"); } } На выходе получаем таблицу с уникальным типом для каждой отдельной детали и одинаковыми для аналогов. Поиск заключается в двух элементарных SELECT, приведенных несколькими постами выше.
ну немножко оптимизировал ваш код точнее полность переоптимизировал, но за идею благодарю Код (Text): $file = fopen("cross.txt", "r"); function get_array($read_file){ while(($arr = fgetcsv($read_file, 1000,"\t"))!== FALSE){ $massiv[] = array_merge($arr); } return $massiv; } $file = get_array($file); $i = 0; foreach ($file as $nums){ $type = ++$i; foreach($nums as $num){ $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$num', '$type')"); } }
вот написал выборку исходя из данных введёных пользователем Код (Text): $user_find = "4D0 898 550"; $zapros = mysql_query("SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'"); $row = mysql_fetch_assoc($zapros); print_r ($row); //выводит найденный результат $otvet = mysql_query("SELECT `number` FROM `crossnumbers` WHERE type_of_number = '$row[type_of_number]'"); for ($r=0; $r<mysql_num_rows($otvet); $r++){ $roww = mysql_fetch_assoc($otvet); echo '<pre>'; print_r ($roww); //выводит отсортированный результат в зависимости от найденного echo '<pre>'; }
ааа, получилось!! Но есть проблемка: как сравнивать введённый номер пользователя с номерами в БД без учёта символов.. пробелы , точки, запятые, тире и т.д. По части номера ищет хорошо с помощью LIKE, а вот как искать какпопалозаписаное - не знаю вот что в итоге у меня получилось: только осталось решить задачу описанную выше. Код (Text): echo '<table border=1>'; $user_find = "622 2400"; $zapros = mysql_query("SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'"); $row = mysql_fetch_assoc($zapros); echo 'Найденый номер в БД'.'<br>'; print_r ($row); //выводит найденый результат $otvet = mysql_query("SELECT `number` FROM `crossnumbers` WHERE type_of_number = '$row[type_of_number]'"); for ($r=0; $r<mysql_num_rows($otvet); $r++){ $roww = mysql_fetch_assoc($otvet); echo 'Результат из БД'; echo '<pre>'; print_r ($roww); //выводит отсортированый результат в зависимости от найденого echo '<pre>'; //**************************************** $file_nalichie = fopen("nalichie.txt", "r"); $file_nalichie = get_array($file_nalichie); //echo 'Результат поиска по файлу'; echo "<tr>"; foreach($file_nalichie as $nalichie) { foreach($nalichie as $numero){ if (are_numbers_equal($numero, $roww['number'])) { //вывод результата в виде таблицы echo "<td style='padding: 6px;'>$nalichie[0]</td><td style='padding: 6px;'>$nalichie[1]</td>"; //если введены данные, выдать найденый результат } } } echo "</tr>"; } echo '</table>'; как мне кажеться.. необходимо чтото дописать тут где LIKE '%$user_find%' Код (Text): "SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'" есть функция у меня Код (Text): function normalize_number($data_corected) { return preg_replace("#\W#", "", $data_corected); }; function are_numbers_equal($number1, $number2) { return strstr(normalize_number($number1), normalize_number($number2)); } с помощью неё я сравниваю уже найденые результаты в БД с номерами в файле но не пойму как применить в нужной мне ситуации, т.е. при сравнении то что ввёл пользователь с номерами в БД
не делайте так никогда. num_rows() - спрашивает у сервера сколько строк в результате. то есть, будет 40 строк - спросит 40 раз, сервер 40 раз пересчитает и вернет цифру 40. если не надо знать только кол-во строк - не используйте num_row() fetch_*() - Возвращает ассоциативный массив строк, соответствующий полученному ряду, либо FALSE если рядов больше нет. вместо ваших двух строк нужно написать одну while( $roww = mysql_fetch_assocc( $otvet ) ){ итераций будет ровно столько, сколько строк в ответе и без лишней нагрузки на сервер. если нужен счетчик - до этой строки объявили (к примеру) i=0 и внутри тела цикла делаем i++ но это было лирическое отступление. в чем у вас проблема сейчас?
Ganzal, в целом верно, только 40 раз будет считать не сервер, а клиент mysql. На самом деле результат запроса уже ждет нас в буфере. Тем не менее в условии for не надо ставить никаких функций, лучший вариант ты показал. Добавлено спустя 3 минуты 23 секунды: Я бы в такой ситуации пошел на избыточность - кроме "правильного" номера хранил бы упрощенный без незначащих символов и инкрементальный поиск вел бы именно по такому варианту. Упростил введеную строку - поискал LIKE по упрощенному полю.
спасибо. принял к сведению! Исправил. а проблемка в следующем: есть номер хранимый в бд в таком виде - EVR15-121.6 пользователь вводит в поиск вот такое 151216 естественно номер не находится если введёт так 15-121.6 то ищет нормально и если так 15-121 вот собственно и проблема чтоб поиск работал без учёта символов точки пробелов запятых тире.....а просто сравнивал цифры или буквы номера