Avatar ·

Функции str_starts_with и str_ends_with в PHP: как проверить начало и конец строки?

Всем привет! Я новичок в PHP и пишу небольшой проект. У меня есть задача: нужно проверять, начинается ли строка с определённого префикса или заканчивается ли она определённым суффиксом. Например, я обрабатываю имена файлов и хочу отфильтровать только те, что начинаются с "report_" или заканчиваются на ".pdf". Я слышал, что в PHP 8 появились функции str_starts_with() и str_ends_with(), но мой проект работает на PHP 7.4, и я не могу обновить версию прямо сейчас. Как мне реализовать такую проверку без этих встроенных функций? Пока я использую substr() для сравнения, но код получается громоздким и не очень читаемым. Вот пример: ```php $filename = "report_q1_2024.pdf"; $prefix = "report_"; $suffix = ".pdf"; if (substr($filename, 0, strlen($prefix)) === $prefix) { echo "Начинается с префикса"; } if (substr($filename, -strlen($suffix)) === $suffix) { echo "Заканчивается на суффикс"; } ``` Это работает, но мне кажется, что есть более элегантные способы. Может, можно написать свои функции-обёртки? Или есть другие трюки с регулярными выражениями? Подскажите, как лучше всего решить эту проблему на PHP 7.4 и ниже, чтобы код был чистым и понятным. Буду благодарен за примеры! <<>>

Проблема и её решение

Вы абсолютно правы: код с substr() работает, но выглядит громоздко. Хорошая новость в том, что вы можете написать свои собственные функции, которые будут работать точно так же, как встроенные str_starts_with() и str_ends_with() из PHP 8. Это сделает код чистым и легко поддерживаемым. Если в будущем вы перейдёте на PHP 8, достаточно будет просто удалить свои функции — имена и сигнатуры совпадают.

Самый простой и правильный способ: свои функции

Создайте две простые функции, которые используют substr() и strlen(), но скрывают всю "грязную" работу внутри:

<?php
function str_starts_with(string $haystack, string $needle): bool {
    return $needle !== '' && substr($haystack, 0, strlen($needle)) === $needle;
}

function str_ends_with(string $haystack, string $needle): bool {
    return $needle !== '' && substr($haystack, -strlen($needle)) === $needle;
}
?>

Почему это хорошо:

  • Читаемость: теперь ваш код будет выглядеть как if (str_starts_with($file, 'report_')) — сразу понятно, что происходит.
  • Безопасность: мы добавили проверку $needle !== '', чтобы избежать ошибок при пустой строке (в PHP 8 эти функции тоже возвращают true для пустого needle, но это спорное поведение).
  • Совместимость: если вы обновитесь до PHP 8, просто удалите эти функции — встроенные будут работать точно так же.

Пример использования

<?php
$files = ['report_2024.pdf', 'draft.txt', 'report_summary.docx', 'image.png'];

foreach ($files as $file) {
    if (str_starts_with($file, 'report_')) {
        echo "Начинается с report_: $file\n";
    }
    if (str_ends_with($file, '.pdf')) {
        echo "Заканчивается на .pdf: $file\n";
    }
}
?>

Вывод:

Начинается с report_: report_2024.pdf
Заканчивается на .pdf: report_2024.pdf
Начинается с report_: report_summary.docx

Дополнительные советы

  • Регулярные выражения не нужны для такой простой задачи — они избыточны и медленнее.
  • Проверяйте аргументы: убедитесь, что $needle не пустая, иначе substr() может вернуть неожиданный результат.
  • Если вы используете фреймворк (Laravel, Symfony), проверьте, нет ли там встроенных хелперов. Например, в Laravel есть Str::startsWith().

Этот подход — золотой стандарт для PHP 7.x. Код становится чистым, а вы не зависите от версии PHP.

<<>>

Альтернативный подход: использование strpos() и strrpos()

Можно также использовать функции strpos() и strrpos() для проверки начала и конца строки. Этот способ чуть более изящен, чем substr(), так как не требует вычисления длины подстроки вручную:

<?php
function starts_with(string $haystack, string $needle): bool {
    return $needle !== '' && strpos($haystack, $needle) === 0;
}

function ends_with(string $haystack, string $needle): bool {
    return $needle !== '' && strrpos($haystack, $needle) === strlen($haystack) - strlen($needle);
}
?>

Как это работает:

  • strpos() возвращает позицию первого вхождения подстроки. Если она равна 0 — строка начинается с needle.
  • strrpos() возвращает позицию последнего вхождения. Если она равна длина строки - длина needle — строка заканчивается на needle.

Плюсы:

  • Не нужно вызывать substr(), что может быть чуть быстрее на больших объёмах данных.
  • Код всё ещё читаемый.

Минусы:

  • Для ends_with() всё равно нужно вызывать strlen().
  • Функции называются не как в PHP 8, поэтому при обновлении придётся менять имена.

Рекомендую всё же первый вариант с substr() и именами, совпадающими с нативными функциями — это более перспективно. Но если вам нужно максимальное быстродействие на PHP 7.4, этот способ тоже хорош.