«Начинается ли моя строка с этого слова?» — извечный вопрос PHP-разработчика
Представьте ситуацию: вы пишете парсер URL, обрабатываете входящие запросы или просто фильтруете список файлов. И тут возникает задача — нужно проверить, начинается ли строка с определённого набора символов. Казалось бы, просто? Но не тут-то было. До недавнего времени в PHP не было встроенной функции для этой простой операции. Разработчики изощрялись кто во что горазд: кто-то обрезал строку через substr(), кто-то искал позицию через strpos(), а кто-то и вовсе лез в дебри регулярных выражений.
В этой статье мы подробно разберём все способы проверки начала строки в PHP. Вы узнаете не только как сделать это «по-красивому» в современных версиях, но и как решить проблему в «старых» проектах, где до сих пор используется PHP 5. Поехали!
Самый правильный способ: str_starts_with() (PHP 8.0+)
Если ваш проект работает на PHP 8.0 или новее — вам повезло. У вас есть нативная функция str_starts_with(), которая делает ровно то, что написано на коробке. Она принимает два аргумента: исходную строку и подстроку, которую мы ищем в начале. Возвращает true или false.
<?php
$url = "https://pythonlib.ru/php-tutorial";
if (str_starts_with($url, "https://")) {
echo "Ссылка безопасная, используем HTTPS";
} else {
echo "Внимание! Не HTTPS соединение";
}
// Выведет: Ссылка безопасная, используем HTTPS
?>
Почему это лучший вариант?
- Читаемость — код говорит сам за себя. Не нужно поясняющих комментариев.
- Производительность — функция оптимизирована на уровне C-кода PHP. Работает быстрее ручных проверок.
- Безопасность — никаких проблем с многобайтовыми кодировками (если только вы не работаете с UTF-8 каким-то особенным образом, но об этом позже).
Кстати, у функции есть «близнец» — str_ends_with(), которая проверяет конец строки. Но это тема для отдельной статьи.
Классический способ: strpos()
До появления str_starts_with() самым распространённым способом было использование функции strpos(). Она ищет первое вхождение подстроки в строке и возвращает его позицию (число). Если подстрока не найдена — возвращает false.
Хитрость в том, что если подстрока находится в самом начале, то её позиция будет 0. А 0 в PHP — это falsy значение. Поэтому проверка должна быть строгой:
<?php
$string = "Hello, world!";
if (strpos($string, "Hello") === 0) {
echo "Строка начинается с Hello";
} else {
echo "Нет, начало другое";
}
?>
Важно! Всегда используйте оператор строгого сравнения ===, а не ==. Почему? Представьте, что вы ищете несуществующую подстроку. strpos() вернёт false. Если написать strpos($string, "test") == 0, то false == 0 даст true (потому что PHP преобразует типы). И ваш код скажет, что строка начинается с "test", хотя это не так. Классическая ловушка для новичков!
Плюсы и минусы strpos()
- ✅ Работает на всех версиях PHP, начиная с 4.
- ✅ Не требует установки расширений.
- ❌ Код менее читаемый — нужно помнить про строгое сравнение.
- ❌ При неправильном использовании (без ===) приводит к трудноуловимым ошибкам.
Дедовский способ: substr()
Ещё один способ, пришедший к нам из глубины веков. Идея проста: вырезать из строки кусок той же длины, что и искомая подстрока, и сравнить их.
<?php
$filename = "report_2024.pdf";
$prefix = "report_";
if (substr($filename, 0, strlen($prefix)) === $prefix) {
echo "Это отчёт за 2024 год";
}
?>
Когда это может быть полезно? Если вам нужно проверить начало и заодно получить остаток строки. Например, чтобы извлечь дату из имени файла.
Недостатки substr()
- ❌ Лишний код — нужно вручную вычислять длину подстроки.
- ❌ Опасность ошибок — легко промахнуться с индексами.
- ❌ Проблемы с многобайтовыми кодировками — если строка содержит кириллицу, обычный
substr()может отработать некорректно. В таком случае используйтеmb_substr().
Тяжёлая артиллерия: регулярные выражения (preg_match)
Когда простых способов недостаточно, на помощь приходят регулярные выражения. Они позволяют проверить начало не просто по статической подстроке, а по целому шаблону.
<?php
$phone = "+7 (123) 456-78-90";
if (preg_match("/^\\+7/", $phone)) {
echo "Российский номер телефона";
} else {
echo "Иностранный номер или неизвестный формат";
}
?>
Символ ^ в регулярном выражении означает «начало строки». Это то, что нам нужно.
Когда это необходимо?
- Когда нужно проверить начало без учёта регистра (добавьте модификатор
i). - Когда нужно проверить один из нескольких вариантов:
/^(http|https|ftp):\\/\\//. - Когда нужно проверить с учётом границ слов.
Но помните: регулярные выражения медленнее обычных строковых функций. Не используйте их там, где можно обойтись str_starts_with() или strpos().
Проблема многобайтовых кодировок (UTF-8)
Все вышеперечисленные способы (кроме регулярных выражений с модификатором u) работают с байтами, а не с символами. Это значит, что если ваша строка содержит кириллицу или иероглифы, вы можете получить неожиданный результат.
Например, строка "Привет" в кодировке UTF-8 занимает 12 байт (каждый символ — 2 байта). Если вы попытаетесь проверить начало с помощью обычного substr(), вы обрежете строку посередине символа и получите «кракозябры».
Решение: используйте mb_* функции:
<?php
$string = "Привет, мир!";
// Неправильно (может не сработать)
if (substr($string, 0, 6) === "Привет") { ... }
// Правильно
if (mb_substr($string, 0, 6) === "Привет") { ... }
// Или просто используйте str_starts_with() — она безопасна для многобайтовых
if (str_starts_with($string, "Привет")) { ... }
?>
Функция str_starts_with() (начиная с PHP 8.0) корректно работает с многобайтовыми кодировками. А вот strpos() и substr() — нет. Помните об этом!
Сравнительная таблица всех способов
Давайте сведём всё в одну удобную таблицу:
| Способ | PHP 8.0+ | PHP 7.x | PHP 5.x | Безопасен для UTF-8 | Скорость | Читаемость |
|---|---|---|---|---|---|---|
| str_starts_with() | ✅ | ❌ | ❌ | ✅ | Высокая | Отличная |
| strpos() === 0 | ✅ | ✅ | ✅ | ❌ | Высокая | Средняя |
| substr() | ✅ | ✅ | ✅ | ❌ | Высокая | Низкая |
| preg_match() | ✅ | ✅ | ✅ | ✅ (с u) | Низкая | Зависит от паттерна |
| mb_substr() | ✅ | ✅ | ✅ | ✅ | Средняя | Низкая |
Итог: что выбрать в 2024 году?
Если вы пишете новый код сегодня — используйте str_starts_with(). Это стандартный, современный и правильный способ. Если поддерживаете старый проект — используйте strpos() со строгой проверкой === 0. Регулярные выражения оставьте для случаев, когда нужно проверить сложный шаблон.
И самое главное — всегда помните о многобайтовых кодировках. Если ваши данные содержат нелатинские символы, тестируйте код на реальных данных. Не надейтесь на «авось».
Пишите чистый код, используйте современные функции, и пусть ошибки с началом строки останутся в прошлом! 🚀