<MyRusakov.ru />

Создание движка на PHP и MySQL 2.0

Создание движка на PHP и MySQL 2.0

Видеокурс "Создание движка на PHP и MySQL 2.0" научит Вас создавать профессиональные движки для сайтов на PHP и MySQL с использованием ООП и паттерна MVC.

В курсе разобрана вся теория по структуре движка: как всё устроено, какие должны быть объекты, какая у них иерархия и как они взаимодействуют между собой.

В практической части будет создан движок с чистого листа. Будет создано ядро, все адаптеры, все вспомогательные классы, а также классы для работы с объектами базы данных. И чтобы курс был максимально полезным, будет создан движок для сайта MyRusakov.ru.

Подробнее
Подписка

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Каким движком Вы предпочитаете пользоваться?

Реализация поиска на сайте через PHP

Реализация поиска на сайте через PHP

У меня уже несколько раз просили написать статью о том, как реализовать поиск на сайте через PHP. Задача это непростая, я бы даже сказал - очень непростая, поскольку здесь имеется огромное количество нюансов и препятствий. В этой статье я разберу алгоритм поиска на сайте.

Давайте предположим, что на нашем сайте имеется множество различных материалов (статей, новостей, заметок и прочего). Всё это добро находится в базе данных. И наша задача - реализовать поиск на сайте. Простейший алгоритм следующий:

  1. Создать HTML-форму со строкой поиска, а также кнопкой "Submit". В текстовое поле пользователи будут вводить поисковый запрос, а далее нажимать на кнопку.
  2. Получить поисковый запрос (как правило, передаваемый методом GET, но иногда применяют и POST), а также, в целях защиты от XSS, пропустить его через функцию htmlspecialchars().
  3. Сделать выборку из соответствующих таблицы (со статьями, новостями, заметками и прочим) тех записей, в которых содержится поисковый запрос. Показываю примерный SQL-запрос для таких случаев: SELECT * FROM articles WHERE `text_article` LIKE %search%Соответственно, вместо search подставляется строка поиска.
  4. Получив записи, в нужном виде выводим их, желательно, по релевантности. Я, например, сделал у себя на сайте так: где больше всего совпадений - та статья и релевантнее, следовательно, ставлю её первой. Скорее всего, Вам этот способ оценки релевантности тоже подойдёт.

Многие из Вас скажут, что ничего сложного здесь нет. И будут отчасти правы, однако, давайте разберём такой пример строки поиска: "ищу этот текст". Встаёт вопрос: "А что, собственно, ищется?". То ли ищется точное вхождение текста "ищу этот текст". Или, быть может, ищется текст, где присутствуют все три слова, но которые могут следовать далеко не друг за другом. Или, возможно, ищется текст, где присутствует хотя бы одно из этих слов.

И вот здесь задача значительно усложняется. Можно сделать сложную систему синтаксиса (как в поисковых системах), например, ищется точное вхождение, если запрос задан в кавычках. А можно давать выбор пользователям, как именно они хотят проводить поиск (с помощью radio-кнопок). Таким образом, сделано у меня на сайте. Поэтому в предыдущий алгоритм добавляется ещё один пункт: составление SQL-запрос. Вот пример SQL-запроса, когда нужно вытащить все материалы, в которых имеется хотя бы одно слово из запроса "ищу этот текст":

SELECT * FROM articles WHERE (`text_article` LIKE "%ищу%" OR `text_article` LIKE "%этот%" OR `text_article` LIKE "%текст%")

Соответственно, в скрипте поиска Вы должны генерировать подобные SQL-запросы, посылать к базе данных, получать ответ и выводить его. Это всё ещё больше усложняется, если Вы выводите записи по релевантности, так как трудно сразу сказать, что должно быть релевантнее: 3 точных вхождения запроса, либо 10 вхождений частей запроса. У меня на сайте предпочтение всегда отдаётся точным вхожденияи, но этот момент уже достаточно спорен. Безусловно, это сложно, и если это Вы делаете в первый раз, то несколько часов Вы точно потратите. Надеюсь, что мой алгоритм реализации поиска на сайте через PHP Вам поможет.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (56):

Trust Trust 15.12.2011 15:25:51

Михаил а вместо text_article Что ставить? Это адрес столбца? И как потом выводить данные правильно, а то я уже много способов перепробовал, не могу сделать так как нужно.

Ответить

Admin Admin 15.12.2011 17:37:28

text_article - это поле, в котором содержится полный текст материала, по которому и ведётся поиск. Выводить надо через SQL-запросы, а, получив result_set, разобрать его на одномерные массивы, элементы которого выводятся уже через echo.

Ответить

Trust Trust 18.12.2011 18:39:47

Михаил а вот если поиск реализуется по таблице users и ищет он только например по колонке name а если человек начинает вводить и фамилию то поиск ступорится и все найти ничего естесственно не может, сейчас у меня завпрос такой : ("SELECT * FROM `users` WHERE `name` LIKE '%{$user_get}%'"); Пробую сделать вроде бы понятно и логично вот так : ("SELECT * FROM `users` WHERE `name` LIKE '%{$user_get}%' AND `familia` LIKE '%{$user_get}%'"); Все ровно не хочет искать=((( ЧТо делаю не так Михаил?!

Ответить

Admin Admin 18.12.2011 19:10:18

А зачем фигурные скобки здесь: {$user_get}? Попробуйте так: LIKE '%$user_get%'

Ответить

Trust Trust 18.12.2011 20:58:14

Так разницы то нет, разве что в скорости выполнения, а вот не могу понять как обьеденить в поисковом запросе 2 колонки familia и name - вопрос=) Я не могу, что не так сделал?!

Ответить

Admin Admin 18.12.2011 21:10:41

Ваш запрос какой-то не логичный. Как может у человека совпадать имя И фамилия? Поэтому могу предположить, что надо вместо AND поставить OR.

Ответить

Trust Trust 18.12.2011 21:29:03

Хорошо а вот если пользователь будет вводить в строке поиска и имя и фамилию?! Как тогда ?!

Ответить

Admin Admin 18.12.2011 21:35:55

Тогда не будет и там, и там $user_get. А, во-вторых, Вам надо будет решать, как обрабатывать данные, то ли выводить те записи, где совпало и имя, и фамилия (AND), то ли, где хотя бы одно совпадение (OR). Либо (как у меня в поиске) право выбора: совпадение "и там, и там", либо "там или там".

Ответить

Trust Trust 18.12.2011 21:39:57

А как тогда формировать запрос на совпадения и имени и фамилии?! Подскажите пожалуйста! Я впервые пишу поисковое ядро по 2м калонкам=( ПРи том что это все обрабатывается на аяксе без перезагрузке страницы=)

Ответить

Admin Admin 18.12.2011 21:47:05

Вы уже писали его, там где AND, только вместо $user_get должно быть что-то другое, в первом случае, имя, а в другом - фамилия.

Ответить

Trust Trust 18.12.2011 21:54:28

так в этом случае будет 2 строки поиска ведь?! А мне нужно чтоб все данные писались в одну поисковую строку!

Ответить

Admin Admin 18.12.2011 21:57:33

"SELECT * FROM `users` WHERE `name` LIKE '%{$user_name}%' AND `familia` LIKE '%{$user_surname}%'" - где здесь 2 строки?

Ответить

Trust Trust 18.12.2011 22:19:18

ДА нет это то я сделал, а вот в самом поле ввода как оно должно распознаватся куда отнести это слово а куда это? К какому столбцу к имени или к фамилии?! у меня идет так xmlhttp.open("GET", "getuser.php?name=" + str, true); xmlhttp.send(); за str берется 0е значение

Ответить

Admin Admin 18.12.2011 22:22:29

Значит, нужно добавить ещё одно поле, чтобы не только name=, но и &surname=

Ответить

Trust Trust 18.12.2011 22:24:56

Тогда как это реализованно например в том же контакте все в одной строке?!

Ответить

Admin Admin 18.12.2011 22:29:05

В одной строке, но с несколькими GET. /?a=5&b=7&c=10 - целых 3 параметра, и все в одной строке.

Ответить

Trust Trust 18.12.2011 22:47:47

ТАк все плывет бошка=) Спасибо вам! На сегодня думаю хватит работы=)

Ответить

drasute drasute 02.02.2012 13:01:55

Здравствуй, Миша. А как сделать вывод тех участков найденных текстов, где содержатся ключевые слова?

Ответить

Admin Admin 02.02.2012 13:19:11

Алгоритм здесь достаточно сложный, и Вам придётся подумать самостоятельно, но нужно использовать функции для работы со строками.

Ответить

drasute drasute 03.02.2012 01:32:40

Сделал.. у меня еще небольшой вопрос - как сделать поддержку русских букв в URL? То есть, по умолчанию те же GET-запросы кодируются в адресной строке, а у тебя, например, тот же запрос на странице поиска отображается кириллицей.

Ответить

Admin Admin 03.02.2012 01:46:21

В UTF-8 отправляйте данные в GET, и всё будет в порядке.

Ответить

drasute drasute 03.02.2012 01:58:53

спасибо за ответы!

Ответить

greatt169 greatt169 29.06.2012 20:41:59

Михаил, когда ввожу запрос на английском все работает, как только ввожу любые русские символы выскакивает ошибка Fatal error: Call to a member function fetch_assoc() on a non-object in X:\home\greatsoftware.ru\www\fsearch.php on line 21 Пробовал "SET NAMES cp1251" не помогает, подскажите пожалуйста, что можно сделать.

Ответить

Admin Admin 29.06.2012 21:01:40

Перекодируйте все входные данные в нужную кодировку, возможно, это UTF-8, а не CP1251.

Ответить

leon leon 10.09.2012 12:11:25

Михаил, здравствуйте! У меня к вам вопрос. К примеру это текст в БД (нужный нам текст). $text = ‘ну’; SELECT * FROM articles WHERE text_article LIKE ‘%$text%’ Данный запрос нам вернёт в массив все статьи, где в тексте встречается ‘ну’. А как сделать запрос точного совпадения. Т.е что бы данный запрос нам ничего не вернул.

Ответить

Admin Admin 11.09.2012 14:03:51

Уберите метасимволы %% из запроса, тогда и будет точное совпадение.

Ответить

leon leon 11.09.2012 15:20:30

так он вообще ничего не находит. я имел ввиду что бы находило полное введенное слово. К примеру в БД существует такой текст (это нужный нам текст) если вводишь 'ну' ничего не находило, а если введешь 'нужный' то находило.

Ответить

Admin Admin 11.09.2012 15:31:32

Тогда через регулярные выражения ищите. Попробуйте вот этот запрос, он должен искать конкретное слово "word": SELECT * FROM table WHERE words REGEXP '[[:<:]]word[[:>:]]'

Ответить

igor igor 23.09.2012 19:59:24

Здравствуйте, подскажите, пожалуйста, а как вернуться к результатам поиска? Например, юзер делал расширенный поиск по 5 параметрам, которые были переданы методом POST. После чего было получено несколько результатов. Юзер, например, открыл один из них, почитал и потом захотел вернуться к остальным полученым. Получается, что надо опять передать эти 5 параметров для поиска или есть какая-нить хитрая штучка у РНР, попроще? Спасибо!

Ответить

Admin Admin 23.09.2012 22:28:52

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

Ответить

alexandr_93 alexandr_93 19.12.2012 23:28:13

Здравствуйте, Михаил! Подскажите пожалуйста, как реализовать поиск по нескольким таблицам в базе данных. Заранее благодарю)

Ответить

Admin Admin 20.12.2012 04:26:45

http://myrusakov.ru/sql-union.html и http://myrusakov.ru/sql-select-several.html

Ответить

cocky cocky 09.03.2013 02:23:31

Здравствуйте, Михаил! Кроме этой статьи, я просмотрел Ваше видео о реализации поиска на сайте. Даже вмонтировал его себе на сайт. Но, как оказалось, функция выводит только один столбик таблицы. Подскажите пожалуйста, как вывести не только саму статью, но и автора, описание, ссылку и т.д. Спасибо.

Ответить

Admin Admin 09.03.2013 11:10:13

Не помню, что там было в уроке, сомневаюсь, что я там выводил один столбик. Но если это так, то надо вместо SELECT `id` FROM - например, поставить SELECT * FROM

Ответить

cocky cocky 09.03.2013 19:20:29

<?php if (isset($_POST['bsearch'])) { echo "<h1>результаты поиска</h1>"; if ($results === false) echo "пустой запрос"; if (count($results) == 0) echo "ничего не найдено"; else for ($i = 0; $i < count($results); $i++) echo $results[$i]["text_article"]."<br />"; } ?> я имел ввиду нечто другое вот код, который вы писали, выводится только текст статьи, тоесть text_article, а как вывести и название, тоесть title ???

Ответить

Admin Admin 09.03.2013 20:57:02

echo $results[$i]["title"]." ".$results[$i]["text_article"]."<br />"; И вот с этой статьёй ознакомьтесь: http://myrusakov.ru/php-how-study.html

Ответить

cocky cocky 09.03.2013 21:54:29

спасибо, ознакомлюсь

Ответить

emulexx emulexx 28.05.2013 22:05:04

Здравствуйте Михаил! Подскажите пожалуйста, как реализовать поиск по разделам сайта с переключением в выпадающем списке. Сайт строю на движке по Вашим урокам. Например, есть 1 раздел Тексты песен и 2 раздел Ноты, все данные хранятся в БД в 2х таблицах. Бывает что и в первой и во второй таблице есть одна и та же песня, только в одной текст, в другой ноты. При обычном поиске если вводить название песни и в результатах поиска у меня выводится сначала текст песни, затем повторно выводится этот текст, а потом уже идет результат с нотами. Если же в таблице БД с нотами поменять название песни на другое, то результат поиска получается отлично. Вот поэтому подумал сделать поиск по разделам, только не знаю как... Помогите пожалуйста или подскажите как.

Ответить

Admin Admin 29.05.2013 04:21:57

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

Ответить

emulexx emulexx 29.05.2013 22:59:25

Можете пожалуйста написать sql запрос, который будет выводить из БД на основании выбора пользователем раздела поиска? В main.tpl я сделал такую вещь <form name = "search" action = "%address%" method = "get" id = "searchform"> <input type = "text" name = "words" value = 'поиск...' onblur = 'if (this.value == "") this.value = "поиск...";' onfocus = 'if (this.value == "поиск...") this.value = "";' /> <input type = "hidden" name = "view" value = "search" /> <div id = "searchcat"> <select name = "choice"> <option value = "songtext">Тексты песен <option value = "noty">Ноты </select> </div> <input type = "submit" name = "search" value = "Найти!" /> </form> Просто не знаю как прикрутить этот choice к БД, извините, новичок =)

Ответить

Admin Admin 30.05.2013 04:20:35

Надо писать ровно такой же запрос как в статье, но таблицу, из которой делается выборка, выбирать через if.

Ответить

Adrenalin Adrenalin 14.09.2013 20:22:03

что-то у меня не выходит! А можно если не сложно код (пример выборки из базы данных то что ввели и вывод результата на екран)?

Ответить

Adrenalin Adrenalin 17.09.2013 13:04:01

например: ввели 3 слова; нужно вывести на екран любое из етих слов или все три.

Ответить

Admin Admin 17.09.2013 19:36:56

Если не выводит, скорее всего просто в запросе ошиблись. Вводите их напрямую в phpmyadmin, чтобы ошибку найти.

Ответить

Adrenalin Adrenalin 26.09.2013 12:21:13

В Денвере слово Город заменяет на город и выводит, а на хостинге находит только так как ввести! В чём проблема? Что-то слышал о регистре. Может оно? Можно пример кода (функции)? Спасибо.

Ответить

Admin Admin 26.09.2013 18:15:12

В кодировке. Если на конце _ci, то она нечувствительна к регистру.

Ответить

Adrenalin Adrenalin 26.09.2013 18:27:37

Кодировке в phpmyadmin или в кодировке моего сайта (скрипта-обработчика)? У меня на компе ОС Виндовс, а у них на хостинге Linux. И вот что они пишут по этому поводу: "Г и г одинаковыми считаться не будут. На любом Linux-сервере это правило присутствует, это особенность Linux-платформы."

Ответить

Adrenalin Adrenalin 29.09.2013 17:29:04

Мне нужны 2 твои ответа на мой последний комментарий! Спасибо.

Ответить

Admin Admin 29.09.2013 18:35:16

Это похоже на проблему в кодировке самой базы. У Вас какая была выбрана при её создании?

Ответить

Adrenalin Adrenalin 30.09.2013 12:18:42

при создании не помню, но я менял её уже по всякому! и если при подключении посылать кирилицу без _ci, то всё работает, но Г и г - это разное, а мне для поиска на сайте это не подходит. Что это за ошибка и как правильно указать кодировку для оператора LIKE если у меня всё всё всё на кирилице (виндовс): Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation 'like'

Ответить

Adrenalin Adrenalin 03.10.2013 13:03:46

наверное так будет правильней: как послать запрос на выборку из базы не точных совпадений, например оператор LIKE, но так, чтобы находило большие буквы и маленькие; если на хостинге Линукс???

Ответить

Admin Admin 03.10.2013 13:07:16

http://myrusakov.ru/mysql-case-search.html

Ответить

ermolmolotov ermolmolotov 07.11.2013 00:43:03

Михаил. Спасибо вам огромное за статью. Я очень и очень внимательно её прочёл.И у меня получилось с попытки #14.))) Конечно потратил 3 дня на это. Зато, поиск получился отличный. Спасибо вам огромное за такие уникальные статьи!!!

Ответить

Alexey25 Alexey25 25.01.2015 14:39:31

У меня такая проблема есть список каталогов, которые обозначены в базе данных в поле через запятую и нужно вынимать те записи где попадается слово обозначения каталого, все каталоги будут прописываться через get запрос через запятую, как php обозначить что например каталог test и test site разделеные запятыми это два разных слова, а то поиск ищет везде где обозначено слово test. Вот исходники: function search($words) { $words = htmlspecialchars($words); if($words === "") return false; $query_search = ""; $array_words = explode(",",$words); foreach($array_words as $key=>$value) { if(isset($array_words[$key-1])) $query_search .= ' OR '; $query_search .= 'type LIKE "%'.$value.'%"'; } $query = "SELECT * FROM system_position WHERE $query_search"; $result = mysql_query($query); $i = 0; while($row = mysql_fetch_array($result)) { $results[$i] = $row; $i++; } return $results; } $results = search($_GET['type']); for($i = 0; $i<count($results); $i++) { echo $results[$i]["id"]."<br>"; }

Ответить

Utopio Utopio 08.04.2015 12:34:33

Здравствуйте, Михаил. Подскажите, слеует ли подменять GET-параметр в адресной строке с русскими символами на английские при поисковом запросе? И как это лучше реализовать?

Ответить

davidoff davidoff 03.06.2015 23:21:34

Для данного поиска, который описан в примере, имеет значение формат базы данных: Myisam или innodb ?

Ответить

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.