Зачем проверять начало и конец строки в PHP?
Представьте: вы пишете сайт на PHP, и вам нужно проверить, заканчивается ли имя файла на .jpg? Или начинается ли email с admin? Раньше для этого приходилось писать костыли с substr() или регулярными выражениями. Но начиная с PHP 8.0, у нас есть элегантное решение — функции str_starts_with() и str_ends_with().
Это не просто синтаксический сахар. Это быстрые, читаемые и безопасные способы работы со строками, которые должен знать каждый PHP-разработчик. В этой статье мы разберем их на реальных примерах, сравним со старыми подходами и покажем, как не допустить типичных ошибок.
Что такое str_starts_with и str_ends_with?
Обе функции появились в PHP 8.0 (вышла в ноябре 2020 года). Они решают одну простую задачу: проверить, содержит ли строка заданный префикс (начало) или суффикс (конец).
Сигнатура функций
str_starts_with(string $haystack, string $needle): bool
str_ends_with(string $haystack, string $needle): bool
$haystack— строка, в которой ищем (стог сена).$needle— подстрока, которую ищем (иголка).- Возвращают
trueилиfalse.
Простейший пример
echo str_starts_with('Hello, world!', 'Hello'); // true
echo str_ends_with('Hello, world!', 'world!'); // true
echo str_starts_with('Hello, world!', 'world'); // false
Важно: функции чувствительны к регистру. str_starts_with('PHP', 'php') вернёт false. Если вам нужно регистронезависимое сравнение — используйте strtolower() или strtoupper() для обеих строк.
Реальные примеры использования
1. Проверка расширения файла
$filename = 'report_2024.pdf';
if (str_ends_with($filename, '.pdf')) {
echo "Это PDF-документ";
} elseif (str_ends_with($filename, '.jpg')) {
echo "Это изображение";
} else {
echo "Неизвестный формат";
}
Раньше это делали через substr($filename, -4) — легко ошибиться с длиной суффикса. Теперь код читается как обычный английский: «строка заканчивается на».
2. Валидация URL или email
$email = 'user@gmail.com';
$url = 'https://pythonlib.ru';
if (str_ends_with($email, '@gmail.com')) {
echo "Пользователь Gmail";
}
if (str_starts_with($url, 'https://')) {
echo "Безопасное соединение";
}
3. Фильтрация массива строк
$files = ['image.jpg', 'document.pdf', 'photo.png', 'notes.txt'];
$images = array_filter($files, function($file) {
return str_ends_with($file, '.jpg') || str_ends_with($file, '.png');
});
print_r($images); // ['image.jpg', 'photo.png']
Как это работало раньше (и почему новые функции лучше)
До PHP 8.0 разработчики использовали несколько подходов. Давайте сравним их с новыми функциями.
Метод 1: substr()
// Старый способ: проверка начала
if (substr($string, 0, strlen('prefix')) === 'prefix') { ... }
// Новый способ
if (str_starts_with($string, 'prefix')) { ... }
Недостатки старого способа:
- Многословность: нужно вычислять длину подстроки.
- Риск ошибки при отрицательной длине (если
$needleдлиннее$haystack). - Код менее читаемый.
Метод 2: strpos()
// Старый способ: проверка начала
if (strpos($string, 'prefix') === 0) { ... }
// Новый способ
if (str_starts_with($string, 'prefix')) { ... }
С strpos легко допустить логическую ошибку: если не поставить === 0, а просто == false или == 0, то при совпадении вы получите неверный результат (потому что 0 == false в PHP — это правда!).
Метод 3: Регулярные выражения
// Старый способ: проверка конца
if (preg_match('/\.pdf$/', $filename)) { ... }
// Новый способ
if (str_ends_with($filename, '.pdf')) { ... }
Регулярки — мощный инструмент, но для простой проверки начала/конца строки это «стрельба из пушки по воробьям». Они медленнее и сложнее для чтения.
Важные нюансы и подводные камни
1. Пустая строка в $needle
Если передать пустую строку в качестве искомой подстроки, обе функции вернут true:
var_dump(str_starts_with('abc', '')); // true
var_dump(str_ends_with('abc', '')); // true
Это логично: любая строка начинается и заканчивается пустой строкой. Помните об этом при проверках.
2. Регистрозависимость
Функции чувствительны к регистру. Если вам нужно игнорировать регистр, приведите обе строки к одному регистру:
$string = 'Hello World';
$prefix = 'hello';
// Не сработает
var_dump(str_starts_with($string, $prefix)); // false
// Правильный способ
var_dump(str_starts_with(
strtolower($string),
strtolower($prefix)
)); // true
3. Работа с многобайтовыми кодировками (UTF-8)
Функции str_starts_with и str_ends_with работают на уровне байтов, а не символов. Для большинства случаев (ASCII) это нормально. Но если вы работаете с UTF-8 строками, содержащими кириллицу или эмодзи, лучше использовать многобайтовые аналоги:
// Для UTF-8 используйте mb_strpos или mb_substr
if (mb_strpos($utf8_string, $prefix) === 0) {
echo "Начинается с префикса";
}
// Или напишите свою обертку
function mb_starts_with($haystack, $needle) {
return mb_strpos($haystack, $needle) === 0;
}
Почему это важно? Потому что кириллические символы занимают 2 байта в UTF-8, и str_starts_with('Привет', 'Пр') может работать некорректно, если строка содержит смешанные кодировки.