Способы отыскания города в PHP приложениях

Раздел: Веб-разработка -> Поисковые функции

Реализация поиска города в PHP: от простого к сложному

Наиболее эффективное решение для поиска городов в больших наборах данных - использование полнотекстового индекса MySQL (InnoDB FULLTEXT).


// Создание таблицы
CREATE TABLE cities (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(200) NOT NULL,
    region VARCHAR(100),
    FULLTEXT INDEX ft_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Search php search author (поиск по автору в php)


// PHP код
$pdo = new PDO('mysql:host=localhost;dbname=geo;charset=utf8mb4', 'user', 'pass');
$stmt = $pdo->prepare("SELECT name, region FROM cities WHERE MATCH(name) AGAINST(:query IN NATURAL LANGUAGE MODE) LIMIT 10");
$stmt->execute(['query' => $searchTerm]);
$cities = $stmt->fetchAll();

Index php act search ru (поиск с параметром ru в php)

Проблема: если названия короткие (менее 4 символов), FULLTEXT игнорирует их. Необходимо изменить параметр ft_min_word_len в конфигурации MySQL или использовать BOOLEAN MODE с оператором *. Также требуется правильная кодировка utf8mb4 для поддержки кириллицы.

Как выполнить простой поиск города по началу названия в PHP?

Использование оператора LIKE с подстановочным знаком %.

$stmt = $pdo->prepare("SELECT name FROM cities WHERE name LIKE ? LIMIT 10");
$stmt->execute([$searchTerm . '%']);

Advance search php (расширенный поиск в php)

LIKE не использует индексы при поиске с подстановкой в начале (например, '%город'), но префиксный LIKE (начало слова) может использовать индекс. Однако при больших объёмах данных производительность падает.

Цель: быстрый старт для таблиц с небольшим количеством записей (до нескольких тысяч).

Как найти город в массиве без базы данных?

При статическом списке городов (например, из файла) можно использовать array_filter или бинарный поиск.

$cities = ['Москва', 'Санкт-Петербург', 'Новосибирск'];
$result = array_filter($cities, fn($city) => stripos($city, $searchTerm) !== false);

Search php vars (переменные поиска в php)

Массив целиком загружается в память, поиск линейный. Для больших списков (сотни тысяч) это неэффективно.

Цель: небольшой справочник городов в конфиге или при отсутствии базы данных.

Как обратиться к OpenStreetMap для поиска города?

Внешнее API Nominatim предоставляет данные о городах мира.

$url = "https://nominatim.openstreetmap.org/search?q=" . urlencode($searchTerm) . "&format=json&limit=10";
$response = file_get_contents($url);
$data = json_decode($response, true);

Search php search id 2 (поиск по id 2 в php)

Ограничение по количеству запросов (1 запрос в секунду), необходимо указывать User-Agent. Зависимость от интернет-соединения и работоспособности сервиса.

Цель: получение актуальных и полных данных о населённых пунктах без ведения собственной базы.

Как организовать динамические подсказки при вводе города?

Создание PHP endpoint, который возвращает JSON, и фронтенд с JavaScript.

// server.php
header('Content-Type: application/json');
$search = $_GET['term'];
// запрос к БД
echo json_encode($cities);

Search php key (поиск по ключу в php)

Необходимо защитить endpoint от XSS и SQL-инъекций. Следует кэшировать частые запросы.

Цель: улучшение пользовательского опыта на сайте.

Как реализовать высокопроизводительный поиск через Elasticsearch с PHP?

Для масштабируемых приложений используется поисковый движок Elasticsearch.

$client = ClientBuilder::create()->build();
$params = ['index' => 'cities', 'body' => ['query' => ['match' => ['name' => $searchTerm]]]];
$response = $client->search($params);
Требуется установка и настройка Elasticsearch, потребление ресурсов. Избыточно для небольших проектов.

Цель: высокая скорость поиска при больших объёмах данных и сложных запросах (автодополнение, исправление опечаток).

- Search php search id 0 (поиск по id 0 в php)
- Index php act search query (поиск с параметром query в php)
- Search city php (поиск города в php)

Расширенные примеры программного кода для поиска городов

Пример 1: Полнотекстовый поиск с булевым режимом и префиксным оператором

Этот метод позволяет искать города по началу названия с ранжированием по релевантности.

Пример

// Создание индекса (уже есть)
// PHP
$query = 'санкт*'; // префиксный поиск
$stmt = $pdo->prepare("SELECT name, region, MATCH(name) AGAINST(:q IN BOOLEAN MODE) AS relevance FROM cities WHERE MATCH(name) AGAINST(:q IN BOOLEAN MODE) ORDER BY relevance DESC LIMIT 20");
$stmt->execute(['q' => $query]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
Array
(
    [0] => Array
        (
            [name] => Санкт-Петербург
            [region] => Ленинградская область
            [relevance] => 2.5
        )
    [1] => Array ( ... )
)

Пример 2: Кэшированный запрос к API Nominatim

Для соблюдения ограничений и ускорения работы используется кэш.

Пример

function searchCityFromNominatim($query) {
    $cacheDir = 'cache/';
    if (!is_dir($cacheDir)) mkdir($cacheDir, 0777, true);
    $cacheFile = $cacheDir . md5($query) . '.json';
    if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
        return json_decode(file_get_contents($cacheFile), true);
    }
    $url = "https://nominatim.openstreetmap.org/search?q=" . urlencode($query) . "&format=json&limit=5&addressdetails=1";
    $opts = [
        'http' => [
            'method' => 'GET',
            'header' => "User-Agent: MyApp/1.0\r\n"
        ]
    ];
    $context = stream_context_create($opts);
    $response = file_get_contents($url, false, $context);
    if ($response === false) {
        error_log('Nominatim API error for query: ' . $query);
        return [];
    }
    $data = json_decode($response, true);
    file_put_contents($cacheFile, json_encode($data));
    return $data;
}
// Вызов функции
$cities = searchCityFromNominatim('Томск');
print_r($cities);
// Вывод (сокращен):
Array
(
    [0] => Array
        (
            [place_id] => 12345
            [licence] => ...
            [display_name] => Томск, городской округ Томск, Томская область, Россия
        )
)

Пример 3: Бинарный поиск по отсортированному массиву городов

Для точного совпадения (без частичного) при наличии отсортированного массива.

Пример

function binarySearchCity(array $sortedCities, string $target): int {
    $left = 0;
    $right = count($sortedCities) - 1;
    while ($left <= $right) {
        $mid = (int)(($left + $right) / 2);
        $cmp = strcasecmp($sortedCities[$mid], $target);
        if ($cmp === 0) return $mid;
        if ($cmp < 0) $left = $mid + 1;
        else $right = $mid - 1;
    }
    return -1;
}
$cities = ['Абакан', 'Азов', 'Анапа', 'Архангельск', 'Астрахань'];
$index = binarySearchCity($cities, 'Азов');
echo $index; // 1
1

Поиск города в PHP - comments

En
Search city php (php)