НейроАгент

Функции startsWith() и endsWith() в PHP: Полное руководство

Узнайте, как реализовать функции startsWith() и endsWith() в PHP. Изучите встроенные функции PHP 8.0+ и пользовательские реализации для более старых версий с советами по производительности.

Вопрос

Как написать функции PHP для проверки, начинается ли строка с указанного символа или подстроки, или заканчивается им?

Например:

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 8.0 ввел встроенные функции специально для проверки префиксов и суффиксов строк, обеспечивая наиболее эффективное и читаемое решение.

Функция str_starts_with()

Функция str_starts_with() проверяет, начинается ли строка с указанной подстроки:

php
bool str_starts_with(string $haystack, string $needle): bool

Пример:

php
$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() проверяет, заканчивается ли строка указанной подстрокой:

php
bool str_ends_with(string $haystack, string $needle): bool

Пример:

php
$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() и прямого сравнения

Это наиболее прямой подход:

php
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(), который возвращает позицию первого вхождения:

php
function startsWith($haystack, $needle) {
    return strpos($haystack, $needle) === 0;
}

Источник: TheoryApp

Метод 3: Использование strncmp() для максимальной производительности

Для оптимальной производительности рекомендуется strncmp(), так как он сравнивает только указанное количество символов:

php
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() для поиска позиции последнего вхождения:

php
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():

php
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
<?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
<?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
<?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+, прежде чем реализовывать пользовательские функции:

php
if (version_compare(PHP_VERSION, '8.0.0') >= 0) {
    // Используйте встроенные функции
    $result = str_starts_with($string, $prefix);
} else {
    // Используйте пользовательскую реализацию
    $result = startsWith($string, $prefix);
}

2. Обрабатывайте крайние случаи

Всегда учитывайте крайние случаи, такие как пустые строки и нулевые значения:

php
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. Поддерживайте согласованность

Если вы работаете над существующим кодом, следуйте установленным шаблонам, а не вводите новые реализации.


Источники

  1. How to Use the StartsWith() and EndsWith() Functions in PHP - W3Docs
  2. PHP | startsWith() and endsWith() Functions - GeeksforGeeks
  3. startsWith() and endsWith() functions in PHP - Stack Overflow
  4. New str_starts_with and str_ends_with functions - PHP 8.0 • PHP.Watch
  5. String StartsWith and EndsWith in PHP – TheoryApp
  6. PHP: startsWith & endsWith functions · GitHub
  7. str_starts_with and str_ends_with functions in PHP - Stack Overflow
  8. What’s New in PHP 8 (Features, Improvements, and the JIT Compiler) - Kinsta
  9. PHP 8.0 feature: quality of life improvements | Platform.sh
  10. 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, требованиях к производительности и потребностях в поддерживаемости кода.