За последние 24 часа нас посетили 17630 программистов и 1722 робота. Сейчас ищут 919 программистов ...

Непростой поиск по базе

Тема в разделе "Прочие вопросы по PHP", создана пользователем MaxSkey, 25 мар 2015.

  1. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Здраствуйте.
    Прошу прощение, если такая тема где то проскакивала.. просто обсмотрел уже не один форум, но решение именно этой цели не могу найти.

    Задача у меня состоим вот в чем:
    Есть форма в которой 3 <select>, в которые данные загружаются из базы:
    1. Город (в базе как 'city')
    2. Валюта (в базе как 'currency')
    3. Тип объявления (в базе как 'type')
    ну и соответственно кнопка "Поиск".

    Мне нужно что бы совершался поиск по базе учитывая эти параметры.
    Сейчас мой вариант не понятно как работает, да и работает через раз(даже выкладывать сюда нету смысла).
    Если выбрать все три параметра в соответствии с каким то полем в базе, результат может быть.
    Если один из селектов оставить не выбранным, то ничего в результате нету.

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

    Добавлено спустя 1 минуту 54 секунды:
    Если селект не выбран, какое ему нужно присваивать значение что бы он не учитывался в выборке из базы?
    Пробывал "" то я так понял оно и ищет пустое поле. Та же ситуация " " с пробелом.
     
  2. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Не надо ничего присваивать. Если искать по полю не нужно, то его и не должно быть в запросе.
     
  3. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    То есть, переменная должна существовать только тогда, когда она не = "0"..
    Код (Text):
    1.  
    2.     if(@$_GET['city']!="0")$city=$_GET['city'];
    3.     if(@$_GET['currency']!="0")$currency=$_GET['currency'];
    4.     if(@$_GET['type']!="0")$type=$_GET['type'];
    Но с таким запросом, сортировка корректно работает только если искать по каждому параметру отдельно.
    Код (Text):
    1.  
    2.     $zzz="SELECT jb_board.id_category, jb_board.city, jb_board.cellphone, jb_board.expired, jb_board.exchange, jb_board.place, jb_board.type, jb_board.amount, jb_board.autor, DATE_FORMAT(jb_board.date_add,'%d.%m.%Y, %H:%i') AS dateAdd FROM jb_board WHERE city='".$city."' || id_category='".$currency."' || type='".$type."'";
    Если выбрать к поиску еще один из трех параметров, или все три.. в ответ приходит каким то не понятным образом отсортированные данные..
    К примеру в поле "валюта" все отлично. А вот в поле "город" там кроме выбранного города еще два города появляются.
    Два дня уже не могу понять почему так. Что именно делаю не так?
     
  4. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    у тебя сейчас 3 GET, а вот если бы было больше, допустим 10, ты бы тоже все проверял через if? не проще использовать массив:
    Код (PHP):
    1. $data = array();
    2. foreach(array('city', 'currency', 'type') as $key)
    3. {
    4.     if ( isset($_GET[$key]) AND !empty($_GET[$key]) )
    5.     {
    6.         $data[$key] = $_GET[$key];
    7.     }
    8. } 
    если ты хочешь проверить задана ли переменная это делается при помощи isset, если переменная задана то будет возвращено TRUE
    empty проверяет не пуста ли переменная, если переменная ровна NULL или "" или 0 или FALSE, тогда будет возвращено TRUE

    PS и вообще запомни, ассоциативный массив в РНР это великая вещь, он очень сильно помогает уменьшит код, пользуйся им.
     
  5. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Ну тут согласен. Спасибо, буду разбираться.
    А как быть с некорректностью результата на запрос?
    Код (Text):
    1.    $zzz="SELECT jb_board.id_category, jb_board.city, jb_board.cellphone, jb_board.expired, jb_board.exchange, jb_board.place, jb_board.type, jb_board.amount, jb_board.autor, DATE_FORMAT(jb_board.date_add,'%d.%m.%Y, %H:%i') AS dateAdd FROM jb_board WHERE city='".$city."' || id_category='".$currency."' || type='".$type."'";
     
  6. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Для начала перестаньте писать xуету вот эту:
    За "||" тимлиды ломают пальцы. Вам самому-то приятно читать такую галиматью?

    Есть общепринятый стиль написания длинных SQL запросов:

    Код (Text):
    1. SELECT
    2.     jb.id_category,
    3.     jb.city,
    4.     jb.cellphone,
    5.     jb.expired,
    6.     jb.exchange,
    7.     jb.place,
    8.     jb.type,
    9.     jb.amount,
    10.     jb.autor,
    11.     DATE_FORMAT(jb.date_add,'%d.%m.%Y, %H:%i') AS dateAdd  
    12. FROM
    13.     jb_board jb
    14.     where
    15.         jb.city = 1
    16.         OR jb.id_category = 2
    17.         OR jb.type = 3
    И вот когда написан понятно запрос уже выясняйте почему в вашей выборке появляются две записи с разными городами. Очевидно потому, что что город в ваших условиях выборки у записей не должен совпадать. Если должен, то конструкцию OR меняйте на AND
     
  7. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    где почитать?)))
     
  8. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    в рунатах например на хабре обсуждалось
    http://habrahabr.ru/post/46068/
    Актуальнее для многотабличных запросов, но лично я всегда стараюсь исповедовать такой принцип когда есть необходимость записывать длинный запрос целиком.
     
  9. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    ну я как бы давно форматирую и длинные и короткие. меня смутила формулировка "общепринятый". это как стандарт кодирования уже получается. если есть общепринятое то наверное придется переучиваться, а если не общепринятое то можно сильно и не напрягаться.
    у меня как-то вот так получается:
    Код (Text):
    1. SELECT
    2.     t.field,
    3.     t.field1,
    4.     ...
    5. FROM
    6.     tbl t
    7. INNER JOIN
    8.     table1 t1
    9.         ON
    10.             t1.id=t.id
    11. INNER JOIN
    12.     table2 t2
    13.         ON
    14.             t2.id=t1.id
    15. WHERE
    16.     1=1
    17.         AND
    18.     t.value='foo'
    19.         AND
    20.     t1.value='bar'
    21. GROUP BY
    22.     t.field
    23. ORDER BY
    24.     t.field
     
  10. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Нет общепринятый и стандарт кодирования совершенно разные вещи.
    Нормально получается. Ключевой момент читаемость.
     
  11. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Над конструкцией поработал.
    Если поменять на AND то по отдельности оно не хочет искать. Сразу дает нулевой результат.
    Если выбрать данные из всех трех селектов которые есть в базе, тогда результат есть!
    Но мне нужно что бы селекты и по отдельности работали.
    То есть, выбран один селект.. ну ладно, поищет по одному условию в базе.. есть два значит по двух.
     
  12. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Ну так вы смотрите какие у вас значения пришли из формы то!
    На их основе и подставляйте в запрос условия. Пришло 2 селекта - 2 AND
    Пришло 1 значение, соответственно, только одно условие.
    Если добавите радиобатон "Искать и/или", то, соответственно, если пришли 2 значения из селектов и переключатель включен на "искать ИЛИ", то в запросе будет два "или" вместо "и", в чем проблема?
     
  13. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Вы простите, я просто не слишком силён в таких вещах
    А как в запросе пишется условие? я просто с таким не сталкивался еще.
     
  14. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    А документацию по MySQL отменили? http://pogugli.com/?78968
     
  15. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Что то я пытался найти и понять.. но если не сложно то покажите правильный вариант данной затеи и всё.
    Должно получиться что то типа такого бреда?)
    Код (Text):
    1. FROM
    2.    jb_board  
    3.    where
    4.       IF($city IS NOT NULL) THEN city='".$city."';
    5.       IF($id_category IS NOT NULL) THEN id_category='".$currency."';
    6.       IF($type IS NOT NULL) THEN type='".$type."';
     
  16. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Что за дикая каша у вас в голове? Смесь из php и mysql... Тут надо чётко разделить. mysql - отдельная программа, php - отдельная программа, программа на php формирует правильный SQL-запрос, уже в готовом виде передаёт его mysql (поскольку mysql - программа-сервер, она может принимать запросы от других программ и отдавать им ответы). Поэтому алгоритм должен быть таким:
    1) Сформировать на основе поступивших данных запрос
    2) Передать его программе mysql
    3) Получить ответы и что-то с ними сделать

    Фильтры делаются примерно так:
    Код (PHP):
    1. $db = new mysqli(/*здесь параметры соединения с сервером mysql");
    2. /* Заносим все условия в массив, чтоб потом их можно было удобно объединить одним оператором */
    3. $consitions = [];
    4.  
    5. if (isset($_GET["city"]))
    6.    $conditions[] = "(city = " . (int) $_GET["city"] . ")";
    7. if (isset($_GET["currency"])) // если валюта передаётся числовым id
    8.    $conditions[] = "(currency= " . (int) $_GET["currency"] . ")";
    9. // Следующее - если буквенным кодом
    10. //if (isset($_GET["currency"])) 
    11.    //$conditions[] = "(currency= '" . $db->real_escape_string($_GET["currency"] . "')";
    12. $query = "select * from jb_board";
    13. // Если были какие-то фильтры
    14. if (!empty($conditions)) {
    15.    $query .= " where " . implode(" and ", $conditions);
    16. }
    17. // И т.д. для каждого условия, какие там фильтры у вас есть.
    18. // Готовый запрос (в нём уже нет самих переменных php, есть только их 
    19. // значения - mysql не умеет читать переменные программы php!)
    20. // передаём в mysql
    21. $res = $db->query($query);
    22. // что-то делаем с результатом.
    23.  
    Ну это конечно простейший случай, но думаю, вам есть о чём подумать
     
  17. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Переходить нужно от этой галиматьи к моделям нормальным давно.
    Упрощённо:

    Код (PHP):
    1. // разбор параметров запроса
    2.  
    3. //...
    4.  
    5. $query = 'SELECT ...';
    6. $params = array();
    7. $joiner = 'AND ';
    8.  
    9. if (! empty($city))
    10. {
    11.     $params[] = "city=$city ";
    12. }
    13. if (! empty($type))
    14. {
    15.     $params[] = "type=$type ";
    16. }
    17.  
    18. // ...
    19.  
    20. if ( isset($search_type) AND $search_type == 'or')
    21. {
    22.     $joiner = 'OR ';
    23. }
    24.  
    25. if ( ! empty($params))
    26. {
    27.     $query .= ' WHERE ' . implode($joiner, $params);
    28. )
    29. var_dump($query); 
     
  18. MaxSkey

    MaxSkey Новичок

    С нами с:
    20 мар 2015
    Сообщения:
    10
    Симпатии:
    0
    Спасибо большое))) Очень хороший вариант. И отдельное спасибо за описание.
    Немножко переделал под себя в некоторых местах.
    Все получилось, и работает)))
     
  19. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Показатель того, что полезно читать код используемых фреймворках. Так в Kohana работает Query Builder