Поиск в веб-приложениях на PHP: методы и примеры
Основные методы поиска с параметром query
Наиболее эффективным решением для поиска по текстовым полям в базе данных MySQL является использование полнотекстового индекса (FULLTEXT) и оператора MATCH AGAINST. Этот подход обеспечивает высокую скорость поиска, учитывает релевантность результатов и поддерживает логические операторы (AND, OR, NOT).
// Подготовка запроса с полнотекстовым поиском
$query = $_GET['query'] ?? '';
$stmt = $pdo->prepare("SELECT id, title, MATCH(title, content) AGAINST(:query IN BOOLEAN MODE) AS relevance FROM articles WHERE MATCH(title, content) AGAINST(:query IN BOOLEAN MODE) ORDER BY relevance DESC");
$stmt->execute(['query' => $query]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);Search php vars (переменные поиска в php)
Массив строк с полями id, title, relevance. relevance указывает на степень соответствия.
Search city php (поиск города в php)
Для работы необходимо предварительно создать FULLTEXT индекс на таблице articles по полям title и content:
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title, content);Search php new (поиск новых записей в php)
Типичные проблемы:
- Не создан FULLTEXT индекс - запрос выполняется как простой LIKE, медленно.
- Короткие слова игнорируются (по умолчанию минимальная длина 4 символа). Настройка ft_min_word_len в my.cnf.
- Стоп-слова (stopwords) исключаются из индекса. Можно отключить или изменить список.
- Ввод специальных символов в IN BOOLEAN MODE (+, -, *, "" ) может нарушить синтаксис. Нужно экранировать или использовать IN NATURAL LANGUAGE MODE.
Как выполнить поиск по части строки в базе данных с помощью LIKE?
Оператор LIKE позволяет найти строки, содержащие заданную подстроку. Подходит для небольших таблиц или когда не требуется сложная морфология.
$search = '%' . $query . '%';
$stmt = $pdo->prepare("SELECT * FROM articles WHERE title LIKE :search OR content LIKE :search");
$stmt->execute(['search' => $search]);
$results = $stmt->fetchAll();Search php search id 0 (поиск по id 0 в php)
Проблемы:
- Низкая производительность на больших таблицах, особенно с ведущим процентом (индекс не используется).
- Не чувствителен к регистру только в зависимости от collation.
- Опасность SQL-инъекций при конкатенации строк. Всегда использовать подготовленные запросы.
Как отфильтровать массив данных по сложному шаблону?
Если данные уже получены из базы или другого источника, можно применить фильтрацию на стороне PHP с помощью preg_grep или array_filter.
$data = ['apple', 'application', 'banana', 'apricot'];
$pattern = '/^app/';
$filtered = preg_grep($pattern, $data);
// или
$filtered = array_filter($data, function($item) use ($pattern) {
return preg_match($pattern, $item);
});
print_r($filtered);Search php search id 2 (поиск по id 2 в php)
Array ( [0] => apple [1] => application )
Search php search author (поиск по автору в php)
Проблемы:
- Обработка всего массива в памяти может быть неэффективной при большом количестве данных.
- Необходимо экранировать специальные символы регулярных выражений (preg_quote).
Как организовать высокопроизводительный поиск с морфологией и агрегацией?
Elasticsearch - распределенный поисковый движок. Для PHP существует официальный клиент elasticsearch-php. После установки через Composer можно выполнять запросы.
require 'vendor/autoload.php';
use Elasticsearch\ClientBuilder;
$client = ClientBuilder::create()->build();
$params = [
'index' => 'articles',
'body' => [
'query' => ['match' => ['content' => $query]]
]
];
$response = $client->search($params);
$results = array_column($response['hits']['hits'], '_source');Проблемы:
- Требуется установка и настройка Elasticsearch сервера.
- Необходимо индексировать данные отдельно.
- Сложность настройки анализаторов и маппингов.
Расширенные примеры реализации поиска
Безопасный LIKE поиск с экранированием спецсимволов
$query = $_GET['query'] ?? '';
$search = '%' . str_replace(['%', '_'], ['\\%', '\\_'], $query) . '%';
$stmt = $pdo->prepare("SELECT * FROM articles WHERE title LIKE :search ESCAPE '\\'");
$stmt->execute(['search' => $search]);
$results = $stmt->fetchAll();Возвращает записи, где title содержит точную подстроку $query, включая символы % и _ (как обычные символы).
Полнотекстовый поиск с подсветкой результатов
$query = $_GET['query'] ?? '';
$stmt = $pdo->prepare("SELECT id, title, content FROM articles WHERE MATCH(title, content) AGAINST(:query IN BOOLEAN MODE)");
$stmt->execute(['query' => $query]);
while ($row = $stmt->fetch()) {
$highlightedTitle = preg_replace(
'/(' . preg_quote($query, '/') . ')/iu',
'$1',
$row['title']
);
echo $highlightedTitle . "<br>";
}Заголовки статей с искомым словом, выделенным жирным шрифтом.
Поиск через Elasticsearch с bool запросом
$params = [
'index' => 'articles',
'body' => [
'query' => [
'bool' => [
'should' => [
['match' => ['title' => $query]],
['match' => ['content' => $query]]
],
'minimum_should_match' => 1
]
]
]
];
$response = $client->search($params);
$hits = $response['hits']['hits'];Массив совпадений, где query встречается в одном из полей. Можно добавить boost для повышения веса title.