PHP str_starts_with и str_ends_with: разбор для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Зачем проверять начало и конец строки в 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('Привет', 'Пр') может работать некорректно, если строка содержит смешанные кодировки.

Производительность: стоит

Блоги

Рекомендаций по книгам