Как разработать PHP скрипт поиска для своего сайта
От автора: PHP скрипт поиска является неотъемлемой частью современного ресурса. Но для начинающих разработчиков его реализация может стать «краеугольным камнем». Сегодня я постараюсь объяснить построение такого модуля как можно проще, чтобы его код не испугал вас своей чрезмерной сложностью.
Ищем на PHP
Организация на сайте внутренней системы поиска является важной задачей. Наличие такого функционала значительно поднимает ресурс в глазах любого пользователя. Особенно это касается узкотематических сайтов, контент которых посвящен решению конкретных «проблем». Например, в веб-программировании.
Чаще всего для написания скрипта поиска по сайту на PHP используется связка данного программного языка с MySQL. Для реализации интерактивной поисковой системы применяется технология AJAX. Но сегодня мы не будем «петлять» в таких дебрях, и остановимся на классическом варианте.
Я приведу самый простой пример поиска. В нем не будет проверок наличия соединения с СУБД, проверки результатов возвращаемой выборки и т.д. Все эти тонкости вы сможете добавить самостоятельно. Цель материала – дать общее представление о построении внутренней системы поиска на современном интернет-ресурсе. Поехали!
Для начала приведу код формы для ввода поискового запроса. Это простая разметка, даже без малейших стилевых «изысков».
Поиск по базе данных (php + mysql).
Задача: осуществить поиск по базе данных на php. В качестве входного параметра — строка (одно или несколько слов, числа …).
Решение: используем оператор LIKE в SQL-запросе.
Примеры:
1. Определяем количество строк в таблице, где есть совпадения с $squery по искомой строке:
$sql = "SELECT COUNT(*) FROM products WHERE (product_name LIKE '%$squery%' OR description LIKE '%$squery%')";
2. Получаем все строки из таблицы, где есть совпадения с $squery.
$sql = "SELECT * FROM products WHERE (product_name LIKE '%$squery%' OR description LIKE '%$squery%') LIMIT $start, $limit";
Другие посты
- Замена строки другой строкой. Функции str_replace() и substr_replace() в PHP
- Ошибка при работе с Doctrine: No identifier/primary key specified for Entity
- Форматирование даты в PHP
- Как добавить к дате секунды, минуты, часы, дни и т.д. (php)
- Как обновить значения поля с типом ENUM в таблице базы данных (MySQL)
get_search_form() │ WP 2.7.0
Подключает форму поиска, файл темы searchform.php . Если такого файла в шаблоне темы нет, то будет использован дефолтный код для формы поиска.
Не забывайте про безопасность
В строку поиска, пользователь может вписать что угодно, например рабочий скрипт
Выводимую строку также можно очистить с помощью: esc_attr(), esc_html().
Хуки из функции
Возвращает
null|Строку .
Использование
- echo(true/false)
Нужно ли выводить созданные HTML код на экран.
По умолчанию: true - aria_label(строка)
Значение артирбута . Будет полезен, чтобы отличать несколько форм на одной странице.
По умолчанию: ''
До версии 5.2 параметр назывался $echo , был логическим и отвечал за вывод HTML на экран:
- true — Выводить код на экран.
- false — возвращать для обработки.
По умолчанию: array()
Примеры
#1 HTML формы поиска через файл searchform.php
Создаем файл searchform.php в папке темы с кодом:
Затем, там где нужна форма поиска, вызываем функцию get_search_form() , которая выведет содержимое созданного нами файла searchform.php :
Имейте ввиду, что форма поиска должна отправлять GET запрос на главную страницу сайта: action="" ) и обязательно должен присутствовать параметр s (что искать): .
#2 Фильтр (ограничение) результатов поиска
Кроме параметра запроса s , можно отфильтровать поиск по типу записи. Для этого добавьте в форму еще одно input поле с именем post_type :
В результате при отправке формы (сабмите) мы получит строку запроса вида: ?s=текст&post_type=post . А это значит, что поиск будет проходить не по всем типам записей, а только по типу записи указанному в поле name="post_type" , в данном случае по типу post . По умолчанию там указано: post_type = any (любой тип записи).
Также результаты поиска можно отфильтровать как угодно, используя событие pre_get_posts. Примеры смотрите в описании.
#3 HTML формы поиска по умолчанию
Если в теме нет файла searchform.php , то вызов этой функции выведет HTML формы по умолчанию:
Такая HTML разметка будет выведена если, НЕ установлена поддержка html5 в теме. Напомню, устанавливается она через функцию add_theme_support() так:
add_theme_support( 'html5', array( 'search-form' ) );
Однако, если поддержка html5 включена, то по умолчанию мы получим такой HTML код формы поиска:
То есть тип поля меняется с text на search : type="search" .
Предпочтение стоит отдавать html5 форме, поэтому всегда включайте эту настройку в темах!
#4 HTML формы поиска через хук
Можно не создавать файл темы searchform.php , а изменить HTML код формы через хук get_search_form, который нужно вставлять в файл темы functions.php .
add_filter( 'get_search_form', 'my_search_form' ); function my_search_form( $form ) < $form = ''; return $form; >
Добавить свой пример
Список изменений
| С версии 2.7.0 | Введена. |
| С версии 5.2.0 | The $args array parameter was added in place of an $echo boolean flag. |
Код get_search_form() get search form WP 6.4.1
function get_search_form( $args = array() ) < /** * Fires before the search form is retrieved, at the start of get_search_form(). * * @since 2.7.0 as 'get_search_form' action. * @since 3.6.0 * @since 5.5.0 The `$args` parameter was added. * * @link https://core.trac.wordpress.org/ticket/19321 * * @param array $args The array of arguments for building the search form. * See get_search_form() for information on accepted arguments. */ do_action( 'pre_get_search_form', $args ); $echo = true; if ( ! is_array( $args ) ) < /* * Back compat: to ensure previous uses of get_search_form() continue to * function as expected, we handle a value for the boolean $echo param removed * in 5.2.0. Then we deal with the $args array and cast its defaults. */ $echo = (bool) $args; // Set an empty array and allow default arguments to take over. $args = array(); >// Defaults are to echo and to output no custom label on the form. $defaults = array( 'echo' => $echo, 'aria_label' => '', ); $args = wp_parse_args( $args, $defaults ); /** * Filters the array of arguments used when generating the search form. * * @since 5.2.0 * * @param array $args The array of arguments for building the search form. * See get_search_form() for information on accepted arguments. */ $args = apply_filters( 'search_form_args', $args ); // Ensure that the filtered arguments contain all required default values. $args = array_merge( $defaults, $args ); $format = current_theme_supports( 'html5', 'search-form' ) ? 'html5' : 'xhtml'; /** * Filters the HTML format of the search form. * * @since 3.6.0 * @since 5.5.0 The `$args` parameter was added. * * @param string $format The type of markup to use in the search form. * Accepts 'html5', 'xhtml'. * @param array $args The array of arguments for building the search form. * See get_search_form() for information on accepted arguments. */ $format = apply_filters( 'search_form_format', $format, $args ); $search_form_template = locate_template( 'searchform.php' ); if ( '' !== $search_form_template ) < ob_start(); require $search_form_template; $form = ob_get_clean(); >else < // Build a string containing an aria-label to use for the search form. if ( $args['aria_label'] ) < $aria_label = 'aria-label="' . esc_attr( $args['aria_label'] ) . '" '; >else < /* * If there's no custom aria-label, we can set a default here. At the * moment it's empty as there's uncertainty about what the default should be. */ $aria_label = ''; >if ( 'html5' === $format ) < $form = ''; > else < $form = ''; > > /** * Filters the HTML output of the search form. * * @since 2.7.0 * @since 5.5.0 The `$args` parameter was added. * * @param string $form The search form HTML output. * @param array $args The array of arguments for building the search form. * See get_search_form() for information on accepted arguments. */ $result = apply_filters( 'get_search_form', $form, $args ); if ( null === $result ) < $result = $form; >if ( $args['echo'] ) < echo $result; >else < return $result; >>
Cвязанные функции
Подключение файлов темы
- comments_template()
- get_footer()
- get_header()
- get_parent_theme_file_path()
- get_parent_theme_file_uri()
- get_sidebar()
- get_stylesheet_directory()
- get_stylesheet_directory_uri()
- get_stylesheet_uri()
- get_template_directory()
- get_template_directory_uri()
- get_template_part()
- get_theme_file_path()
- get_theme_file_uri()
- get_theme_root_uri()
- is_page_template()
- load_template()
- locate_template()
Основные
- bloginfo()
- calendar_week_mod()
- get_archives_link()
- get_bloginfo()
- get_calendar()
- get_current_blog_id()
- is_404()
- is_active_sidebar()
- is_admin()
- is_archive()
- is_attachment()
- is_author()
- is_category()
- is_comment_feed()
- is_date()
- is_day()
- is_dynamic_sidebar()
- is_embed()
- is_feed()
- is_front_page()
- is_home()
- is_month()
- is_paged()
- is_post_type_archive()
- is_preview()
- is_search()
- is_single()
- is_singular()
- is_ssl()
- is_sticky()
- is_tag()
- is_tax()
- is_year()
- language_attributes()
- post_type_archive_title()
- register_sidebar()
- setup_postdata()
- the_archive_description()
- the_archive_title()
- wp_enqueue_script()
- wp_enqueue_style()
- wp_footer()
- wp_get_archives()
- wp_get_document_title()
- wp_head()
- wp_login_form()
- wp_login_url()
- wp_loginout()
- wp_logout_url()
- wp_lostpassword_url()
- wp_register()
- wp_title()
35 комментариев
Полезные 2 Вопросы 1 Все
Подскажите, пожалуйста, а какой шаблон вызывает данный поиск? И по чем именно идет поиск ? * ввел так как указано в примере, но оно не находит посты которые содержат указаные слова запроса не те что содержались в Title не те которіе из контента content
В описании ведь написано, функцию подключит файл темы searchform.php, если такого файла нет, то выведет HTML формы - примеры того что будет выведено также есть в примерах.
В wp 6.3.2 файл searchform.php буд-то игнорируется виджетом поиска который добавляется в сайд бар. Верстка из searchform.php никак никак не влияет на этот виджет. Подскажите, как кастомизировать этот виджет?
Игровые форумы

Сегодня мы напишем собственный поиск по сайту с использованием PHP и MySQL. Первым делом рассмотрим краткий алгоритм.
Пользователь выполняет POST запрос из формы поиска, этот запрос передается специальному скрипту-обработчику, который должен обработать поисковый запрос пользователя и возвратить результат.
Сначала скрипт должен обработать должным образом запрос пользователя для обеспечения безопасности, затем выполняется запрос к базе данных, который возвращает в ассоциативном массиве результаты, которые должны будут выводиться на экран. Итак, приступим.
Для начала создадим форму поиска на нужной нам странице:
Эта форма и будет отправлять сам поисковый запрос скрипту search.php. Теперь создадим сам скрипт-обработчик. define('DB_HOST', 'localhost');
define('DB_USER', 'имя пользователя бд');
define('DB_PASS', 'пароль');
define('DB_NAME', 'имя базы данных');
if (!mysql_connect(DB_HOST, DB_USER, DB_PASS)) exit('Cannot connect to server');
>
if (!mysql_select_db(DB_NAME)) exit('Cannot select database');
>
mysql_query('SET NAMES utf8');
function search ($query)
<
$query = trim($query);
$query = mysql_real_escape_string($query);
$query = htmlspecialchars($query);
if (!empty($query))
<
if (strlen($query) < 3) $text = '
Слишком короткий поисковый запрос.
';
> else if (strlen($query) > 128) $text = '
Слишком длинный поисковый запрос.
';
> else <
$q = "SELECT `page_id`, `title`, `desc`, `title_link`, `category`, `uniq_id`
FROM `table_name` WHERE `text` LIKE '%$query%'
OR `title` LIKE '%$query%' OR `meta_k` LIKE '%$query%'
OR `meta_d` LIKE '%$query%'";
$result = mysql_query($q);
if (mysql_affected_rows() > 0) <
$row = mysql_fetch_assoc($result);
$num = mysql_num_rows($result);
$text = '
По запросу '.$query.' найдено совпадений: '.$num.'
';
do // Делаем запрос, получающий ссылки на статьи
$q1 = "SELECT `link` FROM `table_name` WHERE `uniq_id` = '$row[page_id]'";
$result1 = mysql_query($q1);
if (mysql_affected_rows() > 0) $row1 = mysql_fetch_assoc($result1);
>
$text .= '
href="'.$row1['link'].'/'.$row['category'].'/'.$row['uniq_id'].'" title="'.$row['title_link'].'">'.$row['title'].'
'.$row['desc'].'
';
> while ($row = mysql_fetch_assoc($result));
> else $text = '
По вашему запросу ничего не найдено.
';
>
>
> else $text = '
Задан пустой поисковый запрос.
';
>
return $text;
>
?> Естественно, данные таблиц БД нужно задать собственные. Рассмотрим, что делает эта функция. Первые 4 строчки обрабатывают запрос, чтобы он стал безопасным для базы. Такую обработку нужно делать обязательно, т. к. любая форма на Вашем сайте — это потенциальная уязвимость для злоумышленников.
Затем идет проверка, не пустой ли запрос. Если запрос пустой, то возвращаем соответствующее сообщение пользователю. Если запрос не пустой, проверяем его на размер.
Если поисковый запрос имеет длину менее 3 или более 128 символов, также выводим соответствующие сообщения пользователю. Иначе, выполняем запрос к базе данных, который делает выборку идентификатора страницы, ее заголовка, описания, описания ссылки, категорию, если она есть и идентификатор самой статьи, в которой найдены совпадения нужных нам полей с поисковым запросом.
В данном случае мы делаем сравнение с текстом статьи, ее заголовком, ключевыми словами и описанием. Если ничего не найдено, выводим пользователю сообщение об этом. Если запрос возвратил хотя бы одну запись, выполняем в цикле еще один запрос, который делает выборку из таблицы со страницами ссылку на страницу, на которой находится статья.
Если у Вас все статьи на одной странице, вы можете опустить этот шаг. После выполнения запроса при каждой итерации цикла в переменную $text Дозаписываем одну найденную статью.
После завершения цикла, возвращаем переменную $text, Которая и будет выводиться на нашей странице пользователю.
Теперь осталось на этой же странице search.php сделать вызов этой функции и вывести ее результат пользователю. if (!empty($_POST['query'])) <
$search_result = search ($_POST['query']);
echo $search_result;
>
?> Также вы можете упростить скрипт поиска по Вашему усмотрению. Желательно создать стиль в таблице css для выводимой информации, чтобы выводимая информация смотрелась более красиво и читабельно. Все замечания вопросы по скрипту можете задавать в комментариях.
не в сети давно
На сайте с 21.11.2014
24 ноября 2014 09:28
Небольшие комментарии:
1. Не указано, в какой кодировке нужно хранить скрипт, в коде есть только
mysql_query('SET NAMES utf8');
Эта команда, устанавливающая кодировку для работы в UTF8. Многие начинающие разработчики сначала используют CP1251 в своих проектах, а это не очень хорошо
Поэтому, или сохраняем все ваши скрипты в UTF8, или меняем внутреннюю кодировку в скрипте командами, например, mb_internal_encoding, mb_external_encoding. Или, в крайнем случае, дописываем к запросам типа SELECT
COLLATE latin1_german2_ci в нужное место, это зависит от типа запроса. Лучше почитать в самой документации MySQL: http://dev.mysql.com/doc/refman/5.0/en/charset-collate.html
2. В запросах не используются placeholder'ы. Это неоптимально и небезопасно:) Легче и лучше использовать готовые PHP-библиотеки, созданные для этого или, как например, класс PDO, вместо mysql_* функций. mysql_* функции уже на момент написания этой статьи были запрещены. Но их все так же можно скачать отдельно к вашему серверу, если это так необходимо:)
не в сети давно
На сайте с 21.11.2014
24 ноября 2014 09:33
А еще!
В коде слишком много конкатенаций в цикле. В случае с PHP это очень и очень грозит утечками памяти:
$text .= '
href="'.$row1['link'].'/'.$row['category'].'/'.$row['uniq_id'].'" title="'.$row['title_link'].'">'.$row['title'].'
'.$row['desc'].'
';
Вместо этого перед циклом нужно объявлять $text = array() (или, для новых версий PHP - $text = [];), выделяя ему определенный размер в памяти вместо размера для текста-контейнера.
Далее в цикле вместо $text.= нужно использовать $text[]=
И, наконец, после завершения цикла, текст получать командой implode('', $text), собирающей массив воедино:)
не в сети давно
На сайте с 15.02.2015
15 февраля 2015 16:46
В целом код полезный, и со своей задачей справляется, только новичкам будет сложно его понять. Слишком много условий, в них легко запутаться. Я не вижу чтобы Вы выводили из таблицы поля text, meta_k, и meta_d, хотя производите по ним поиск. Почему не выводится meta я могу понять, но текст где? Если полный текст статьи вывести нельзя, то нужно показывать хотя бы отрезок с совпадением, чтобы пользователь его видел. Я на своем сайте, чтобы результаты поиска были нагляднее, подсвечивал совпадение светло-зеленым фоном. Очень красиво получалось. Очень огорчает наличие всего одного комментария, и того в самом очевидном месте. Хороший программист знает как сделать поиск на сайте, а в такие темы попадают в основном новички (коим и я был не так давно). Не понимая что происходит, они просто копируют весь код, и, осознав что ничего не работает, опускают руки.
не в сети давно
На сайте с 10.02.2015
22 февраля 2015 00:37
Может, код и полезен. Но это под вопросом. Например, функция mysql_real_escape_string() просто не сработает, так как она устарела и вскоре будет вообще заменена. Когда данной функцией пытался защититься от инъекций, то в браузере возникала ошибка, которая не позволяла обрабатывать и последующий код — эта функция срабатывала с выдачей практически фатальной ошибки. А если уж придерживаться функционального стиля, то и подключение к базе следует выводить в отдельной функции, либо вообще выносить в отдельный файл с необходимостью его последующего подключения. А лучше, если константы DB_HOST и другие окажутся также в отдельном файле. В php, хоть и оставили возможность программирования в функциональном стиле, все же отдают теперь предпочтение объектно-ориентированному, а потому приведенный пример немного устарел и не совсем полезен. Не совсем понятно зачем в коде используется вот эта часть: "mysql_query('SET NAMES utf8');". Для примера, на мой взгляд, она совершенно лишняя, ведь по условиям не сказано, что БД и таблицы, к которым обращаемся, в utf-8 кодировке, а, вдруг, у меня БД в кодировке "1251-windows"! :terminator
