Как написать функции PHP для проверки, начинается ли строка с указанного символа или подстроки, или заканчивается им?
Например:
$str = '|apples}';
echo startsWith($str, '|'); //Возвращает true
echo endsWith($str, '}'); //Возвращает true
Какова реализация функций startsWith() и endsWith() в PHP?
PHP предлагает несколько подходов для проверки, начинается ли строка с или заканчивается указанной подстрокой. Для PHP 8.0+ можно использовать встроенные функции str_starts_with() и str_ends_with(), в то время как для более старых версий требуются пользовательские реализации с использованием функций таких как substr(), strpos() или strncmp().
Содержание
- Встроенные функции PHP
- Методы пользовательской реализации
- Соображения по производительности
- Полные примеры реализации
- Лучшие практики и рекомендации
Встроенные функции PHP
PHP 8.0 ввел встроенные функции специально для проверки префиксов и суффиксов строк, обеспечивая наиболее эффективное и читаемое решение.
Функция str_starts_with()
Функция str_starts_with() проверяет, начинается ли строка с указанной подстроки:
bool str_starts_with(string $haystack, string $needle): bool
Пример:
$str = '|apples}';
echo str_starts_with($str, '|'); // Возвращает true
echo str_starts_with($str, 'app'); // Возвращает false
echo str_starts_with($str, ''); // Возвращает true
Функция str_ends_with()
Функция str_ends_with() проверяет, заканчивается ли строка указанной подстрокой:
bool str_ends_with(string $haystack, string $needle): bool
Пример:
$str = '|apples}';
echo str_ends_with($str, '}'); // Возвращает true
echo str_ends_with($str, 'les}'); // Возвращает true
echo str_ends_with($str, ''); // Возвращает true
Важное замечание: Согласно PHP.Watch, эти функции доступны только в PHP 8.0+. Для пустых игл str_starts_with() возвращает true, а str_ends_with() также возвращает true.
Методы пользовательской реализации
Для версий PHP до 8.0 необходимо реализовывать эти функции вручную. Вот несколько подходов:
Метод 1: Использование substr() и прямого сравнения
Это наиболее прямой подход:
function startsWith($string, $startString) {
$len = strlen($startString);
return (substr($string, 0, $len) === $startString);
}
function endsWith($string, $endString) {
$len = strlen($endString);
if ($len == 0) {
return true;
}
return substr($string, -$len) === $endString;
}
Источник: GeeksforGeeks
Метод 2: Использование strpos() для startsWith()
Этот метод использует strpos(), который возвращает позицию первого вхождения:
function startsWith($haystack, $needle) {
return strpos($haystack, $needle) === 0;
}
Источник: TheoryApp
Метод 3: Использование strncmp() для максимальной производительности
Для оптимальной производительности рекомендуется strncmp(), так как он сравнивает только указанное количество символов:
function startsWith($haystack, $needle) {
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
function endsWith($haystack, $needle) {
return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
Источник: GitHub Gist
Метод 4: Использование strrpos() для endsWith()
Этот подход использует strrpos() для поиска позиции последнего вхождения:
function startsWith(string $string, string $start): bool {
return strrpos($string, $start, - strlen($string)) !== false;
}
function endsWith(string $string, string $end): bool {
return ($offset = strlen($string) - strlen($end)) >= 0 &&
substr($string, $offset) === $end;
}
Источник: Stack Overflow
Метод 5: Использование explode() для startsWith()
Творческий подход с использованием explode():
function startsWith($haystack, $needle) {
$cutsQuantity = 2;
$parts = explode($needle, $haystack, $cutsQuantity);
return ($parts[0] === '');
}
Источник: Stack Overflow
Соображения по производительности
Производительность различных реализаций значительно различается, особенно при работе с большими строками:
Сравнение производительности
Согласно результатам тестов с Reddit:
- Подход с
strncmp(): ~0.029958s для 400,000 итераций - Подход с
substr(): ~0.027378s для 400,000 итераций - Подход с
strpos(): ~22.501702s для 400,000 итераций
Разница драматична, потому что strpos() нужно искать по всей строке (сложность O(n)), в то время как strncmp() и substr() проверяют только начало/конец (сложность O(1)).
Эффективность использования памяти
Как отмечено в PHP Backend, некоторые подходы более эффективны с точки зрения памяти, чем другие:
substr()может быть неэффективным с точки зрения памяти, так как создает копии частей строкиstrncmp()эффективен как с точки зрения процессора, так и памяти- Встроенные функции PHP 8.0 оптимизированы для производительности
Полные примеры реализации
Вот полная, готовая к производству реализация, которая работает во всех версиях PHP:
Базовая реализация
<?php
if (!function_exists('startsWith')) {
function startsWith($string, $startString) {
$len = strlen($startString);
return (substr($string, 0, $len) === $startString);
}
}
if (!function_exists('endsWith')) {
function endsWith($string, $endString) {
$len = strlen($endString);
if ($len == 0) {
return true;
}
return substr($string, -$len) === $endString;
}
}
// Пример использования
$str = '|apples}';
echo startsWith($str, '|') ? 'true' : 'false'; // true
echo endsWith($str, '}') ? 'true' : 'false'; // true
echo startsWith($str, 'app') ? 'true' : 'false'; // false
echo endsWith($str, 'les}') ? 'true' : 'false'; // true
Реализация с оптимизацией производительности
<?php
if (!function_exists('startsWith')) {
function startsWith($haystack, $needle) {
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
}
if (!function_exists('endsWith')) {
function endsWith($haystack, $needle) {
if ($needle === '') {
return true;
}
return substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
}
// Пример с пустыми строками
echo startsWith('test', '') ? 'true' : 'false'; // true
echo endsWith('test', '') ? 'true' : 'false'; // true
Версии без учета регистра
<?php
if (!function_exists('startsWithIgnoreCase')) {
function startsWithIgnoreCase($string, $startString) {
return stripos($string, $startString) === 0;
}
}
if (!function_exists('endsWithIgnoreCase')) {
function endsWithIgnoreCase($string, $endString) {
$len = strlen($endString);
if ($len == 0) {
return true;
}
return strtolower(substr($string, -$len)) === strtolower($endString);
}
}
// Примеры без учета регистра
echo startsWithIgnoreCase('Hello World', 'hello') ? 'true' : 'false'; // true
echo endsWithIgnoreCase('Hello World', 'world') ? 'true' : 'false'; // true
Лучшие практики и рекомендации
1. Проверяйте версию PHP в первую очередь
Всегда проверяйте, используете ли вы PHP 8.0+, прежде чем реализовывать пользовательские функции:
if (version_compare(PHP_VERSION, '8.0.0') >= 0) {
// Используйте встроенные функции
$result = str_starts_with($string, $prefix);
} else {
// Используйте пользовательскую реализацию
$result = startsWith($string, $prefix);
}
2. Обрабатывайте крайние случаи
Всегда учитывайте крайние случаи, такие как пустые строки и нулевые значения:
function safeStartsWith($string, $prefix) {
if ($string === null || $prefix === null) {
return false;
}
return startsWith($string, $prefix);
}
3. Выбирайте правильную реализацию
Для максимальной производительности в старых версиях PHP:
- Используйте
strncmp()дляstartsWith() - Используйте
substr_compare()дляendsWith()
4. Рассмотрите возможность использования полифиллов
Для крупных проектов рассмотрите возможность использования библиотеки полифиллов, которая предоставляет эти функции для всех версий PHP. WordPress реализовал полифиллы для этих функций.
5. Поддерживайте согласованность
Если вы работаете над существующим кодом, следуйте установленным шаблонам, а не вводите новые реализации.
Источники
- How to Use the StartsWith() and EndsWith() Functions in PHP - W3Docs
- PHP | startsWith() and endsWith() Functions - GeeksforGeeks
- startsWith() and endsWith() functions in PHP - Stack Overflow
- New
str_starts_withandstr_ends_withfunctions - PHP 8.0 • PHP.Watch - String StartsWith and EndsWith in PHP – TheoryApp
- PHP: startsWith & endsWith functions · GitHub
- str_starts_with and str_ends_with functions in PHP - Stack Overflow
- What’s New in PHP 8 (Features, Improvements, and the JIT Compiler) - Kinsta
- PHP 8.0 feature: quality of life improvements | Platform.sh
- Replace usage of strpos with str_starts_with – WordPress Trac
Заключение
Реализация функций startsWith() и endsWith() в PHP может быть выполнена с помощью встроенных функций PHP 8.0+ или пользовательских реализаций для более старых версий. Встроенные функции str_starts_with() и str_ends_with() обеспечивают наиболее читаемое и производительное решение. Для совместимости со старыми версиями PHP используйте strncmp() и substr_compare() для оптимальной производительности. Всегда учитывайте крайние случаи, такие как пустые строки и нулевые значения, в ваших реализациях. Выбор между различными методами реализации должен основываться на версии PHP, требованиях к производительности и потребностях в поддерживаемости кода.