Avatar ·

Как проверить, содержит ли строка определенное слово в PHP?

Привет всем! Я новичок в PHP и пишу небольшой скрипт для фильтрации комментариев на сайте. Мне нужно проверить, содержит ли текст комментария определенные запрещенные слова, например "спам" или "реклама". Проблема в том, что я не могу найти правильный способ это сделать. Я пробовал использовать оператор ==, но он не работает со строками. Потом я нашел функцию strpos(), но она почему-то находит слово даже внутри других слов. Например, когда я ищу слово "реклама", она находит его в слове "перекламация" — это неправильно. Также я не понимаю, как обрабатывать регистр: слово "Спам" с большой буквы должно тоже считаться совпадением. Вот мой текущий код, который не работает как надо: ```php $text = "Это спам, удалите его!"; $word = "спам"; if (strpos($text, $word) !== false) { echo "Найдено запрещенное слово!"; } else { echo "Текст чист."; } ``` Проблема в том, что если написать "Спам" с большой буквы, то функция не срабатывает. И еще — если слово является частью другого слова, например "пам" в "памятник", то тоже считается совпадением. Подскажите, как правильно реализовать проверку на наличие целого слова, с учетом регистра и границ слов? Буду благодарен за подробное объяснение с примерами. <<>>

Правильный способ проверки наличия слова в строке в PHP

Ваша проблема очень распространена среди начинающих PHP-разработчиков. Давайте разберем несколько решений, от простых к более надежным.

1. Базовое решение с strpos() и учетом регистра

Функция strpos() ищет подстроку в строке, но она чувствительна к регистру. Для регистронезависимого поиска используйте stripos():

<?php
$text = "Это спам, удалите его!";
$word = "спам";

// Регистронезависимый поиск
if (stripos($text, $word) !== false) {
    echo "Найдено запрещенное слово!";
} else {
    echo "Текст чист.";
}
// Выведет: Найдено запрещенное слово!
?>

2. Проблема с границами слов и ее решение

Ваша главная проблема — strpos() находит подстроку внутри другого слова. Например, "пам" будет найдено в "памятник". Чтобы этого избежать, нужно проверять границы слов. Лучшее решение — использовать регулярные выражения с функцией preg_match() и метасимволом \b (граница слова):

<?php
$text = "Этот памятник стоит у дороги";
$word = "пам";

// Используем регулярное выражение с границами слов
if (preg_match('/\b' . preg_quote($word, '/') . '\b/ui', $text)) {
    echo "Найдено целое слово!";
} else {
    echo "Слово не найдено или является частью другого слова.";
}
// Выведет: Слово не найдено или является частью другого слова.
?>

Обратите внимание на важные детали:

  • \b — обозначает границу слова (начало или конец)
  • preg_quote() — экранирует специальные символы регулярных выражений в искомом слове
  • Модификатор u — включает поддержку UTF-8 (для русского языка)
  • Модификатор i — делает поиск регистронезависимым

3. Проверка нескольких слов (массив запрещенных слов)

Часто нужно проверять не одно, а целый список слов. Вот как это сделать эффективно:

<?php
$text = "Купите нашу рекламу! Это не спам.";
$badWords = ['спам', 'реклама', 'покупка'];

$found = false;
foreach ($badWords as $word) {
    $pattern = '/\b' . preg_quote($word, '/') . '\b/ui';
    if (preg_match($pattern, $text)) {
        $found = true;
        echo "Найдено запрещенное слово: " . $word . "<br>";
    }
}

if (!$found) {
    echo "Текст чист.";
}
// Выведет: Найдено запрещенное слово: реклама
//          Найдено запрещенное слово: спам
?>

4. Универсальная функция для проверки

Для удобства можно создать функцию, которую легко переиспользовать:

<?php
/**
 * Проверяет, содержит ли строка указанное слово (целиком, без учета регистра)
 * 
 * @param string $text Текст для проверки
 * @param string $word Искомое слово
 * @return bool true если слово найдено
 */
function containsWord($text, $word) {
    $pattern = '/\b' . preg_quote($word, '/') . '\b/ui';
    return (bool) preg_match($pattern, $text);
}

// Примеры использования
$texts = [
    "Это спам, удалите!",
    "СПАМ в верхнем регистре",
    "памятник (не должно совпасть)",
    "Безопасный текст"
];

foreach ($texts as $t) {
    $result = containsWord($t, "спам") ? "ДА" : "НЕТ";
    echo "Текст: '$t' - Содержит 'спам'? $result<br>";
}

/* Вывод:
Текст: 'Это спам, удалите!' - Содержит 'спам'? ДА
Текст: 'СПАМ в верхнем регистре' - Содержит 'спам'? ДА
Текст: 'памятник (не должно совпасть)' - Содержит 'спам'? НЕТ
Текст: 'Безопасный текст' - Содержит 'спам'? НЕТ
*/
?>

Важные замечания

  • Производительность: Для больших текстов и множества слов лучше сначала разбить текст на слова через str_word_count() или preg_split(), а затем искать в массиве.
  • Кодировка: Всегда проверяйте, что ваш PHP-файл сохранен в UTF-8 без BOM, и используйте модификатор u в регулярных выражениях для корректной работы с кириллицей.
  • Спецсимволы: Если слово содержит точки, вопросительные знаки и т.д., обязательно используйте preg_quote().

Надеюсь, это подробное объяснение поможет вам правильно реализовать проверку слов в PHP! Если остались вопросы — спрашивайте.

<<>>

Альтернативный подход: разбиение строки на массив слов

Вместо регулярных выражений можно разбить текст на отдельные слова и проверить наличие нужного слова в полученном массиве. Этот метод интуитивно понятен и не требует знаний регулярных выражений:

<?php
$text = "Это спам, удалите его!";
$word = "спам";

// Разбиваем текст на слова (убираем знаки препинания)
$words = str_word_count($text, 1, 'А-Яа-яЁё');
// str_word_count с параметром 1 возвращает массив слов

// Проверяем, есть ли слово в массиве (регистронезависимо)
$wordLower = mb_strtolower($word, 'UTF-8');
$found = false;
foreach ($words as $w) {
    if (mb_strtolower($w, 'UTF-8') === $wordLower) {
        $found = true;
        break;
    }
}

echo $found ? "Слово найдено!" : "Слово не найдено.";
// Выведет: Слово найдено!
?>

Плюсы и минусы этого подхода

  • Плюсы: Не требует регулярных выражений, легко читается, хорошо работает с кириллицей.
  • Минусы: Медленнее для больших текстов, требует дополнительной обработки для слов с дефисами или апострофами (например, "какой-нибудь").

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