substr_compare()
Функция substr_compare() в PHP сравнивает части двух строк начиная с указанной позиции и до заданной длины.
Введение
Функция substr_compare() сравнивает часть одной строки с другой строкой, начиная с заданного смещения. Это аналог сравнения подстроки $main_str с $str — но без предварительного вызова substr() для извлечения подстроки. Это делает её идиоматичным и не требующим выделения памяти способом ответить на вопросы вроде «начинается ли эта строка с X?» или «заканчивается ли эта строка на Y?» в старых версиях PHP.
В этой главе объясняются параметры функции, смысл возвращаемого значения и распространённые паттерны (проверка префикса, суффикса, сравнение без учёта регистра), в которых substr_compare() особенно удобна.
Синтаксис
substr_compare(
string $haystack,
string $needle,
int $offset,
?int $length = null,
bool $case_insensitive = false
): intПримечание: Параметр
$lengthявляется необязательным. В PHP 8+ он явно объявлен как nullable (?int); передачаnull(или пропуск параметра) означает сравнение до конца$haystack.
| Параметр | Описание |
|---|---|
$haystack | Основная строка. Сравнение читает часть этой строки. |
$needle | Строка, сравниваемая с частью $haystack. |
$offset | Позиция в $haystack, с которой начинается сравнение. Отрицательное значение отсчитывается с конца $haystack. |
$length | Количество символов для сравнения. Если null, используется наибольшее из оставшейся части $haystack и всей строки $needle. |
$case_insensitive | Если true, регистр букв игнорируется ("A" равно "a"). По умолчанию false. |
Возвращаемое значение
substr_compare() возвращает значение типа int:
0— сравниваемые части равны.- отрицательное число — часть
$haystackменьше$needle(идёт раньше при сортировке). - положительное число — часть
$haystackбольше$needle(идёт позже при сортировке).
Важен знак результата; конкретная величина зависит от реализации и не должна использоваться как надёжный ориентир. Для проверки равенства сравнивайте явно с 0: substr_compare(...) === 0.
Базовый пример
Здесь мы сравниваем первые strlen($string2) (6) символов строки "Hello World!" со строкой "Hello!". Шестой символ — пробел (" ") в первой строке и восклицательный знак ("!") во второй; пробел (ASCII 32) стоит перед ! (ASCII 33), поэтому функция возвращает отрицательное целое число (-1).
Проверка того, начинается ли строка с префикса
Сравнение при смещении 0 с $length, равной длине префикса, является чистым тестом «начинается с»:
<?php
function startsWith(string $haystack, string $prefix): bool
{
return substr_compare($haystack, $prefix, 0, strlen($prefix)) === 0;
}
var_dump(startsWith("php-fpm", "php")); // bool(true)
var_dump(startsWith("python", "php")); // bool(false)В PHP 8.0+ можно использовать встроенную функцию
str_starts_with().substr_compare()остаётся полезной на старых версиях и когда требуется нечувствительность к регистру.
Проверка того, заканчивается ли строка на суффикс
Отрицательное смещение отсчитывается с конца строки, что делает проверки «заканчивается на» простыми — вам не нужно вычислять позицию вручную:
<?php
function endsWith(string $haystack, string $suffix): bool
{
return substr_compare($haystack, $suffix, -strlen($suffix)) === 0;
}
var_dump(endsWith("report.pdf", ".pdf")); // bool(true)
var_dump(endsWith("report.txt", ".pdf")); // bool(false)Сравнение без учёта регистра
Передайте пятым аргументом true, чтобы игнорировать регистр букв:
<?php
$sensitive = substr_compare("Hello", "hello", 0);
$insensitive = substr_compare("Hello", "hello", 0, null, true);
echo $sensitive; // non-zero: 'H' and 'h' differ
echo PHP_EOL;
echo $insensitive; // 0: equal when case is ignoredПодводные камни
- Смещение за пределами диапазона. Положительное
$offset, превышающее длину$haystack, вызываетValueErrorв PHP 8+ (в PHP 7 — предупреждение с возвратомfalse). Проверяйте смещения относительноstrlen($haystack), когда они поступают из пользовательского ввода. $lengthбольше, чем осталось. Если$lengthпревышает количество доступных символов, сравниваются только доступные символы — функция не выдаёт ошибку, просто сравнивает меньше.- Побайтовый режим, не многобайтовый.
substr_compare()работает с байтами. Для текста в UTF-8, где один символ может занимать несколько байт, смещения и длины являются байтовыми, а не символьными.
Связанные функции
strcmp()— бинарно-безопасное сравнение двух строк целиком.strncmp()— сравнивает только первые n символов двух строк.strcasecmp()— сравнение двух строк целиком без учёта регистра.substr()— извлечение части строки.
Заключение
substr_compare() сравнивает часть одной строки с другой без её предварительного извлечения, что делает функцию эффективной для проверки префиксов и суффиксов. Не забывайте сравнивать результат с 0 для проверки равенства, использовать отрицательное $offset для проверок «заканчивается на» и передавать true последним аргументом, когда регистр следует игнорировать.