PHP: substr и мощные альтернативы, чтобы вырезать часть строки

Поговорим о том, как обрезать строку в PHP. Функция substr в предназначена для получения части строки. Она выделяет подстроку из переданной строки и возвращает её. Для этого нужно указать строку, порядковый номер символа, начиная с которого нужно вырезать строку, порядковый номер символа, до которого мы верезаем подстроку.

Обратите внимание, что substr неправильно работает с многобайтовыми кодировками, поэтому мы будем использовать mb_substr, которая работает с ними корректно. Об этой проблеме немного ниже.

Сигнатура функции:

 mb_substr(
    string $string,
    int $start,
    int|null $length = null,
    string|null $encoding = null
): string
  • $string - строка, из которой мы будем вырезать подстроку
  • $start - символ, с которого мы будем вырезать подстроку
  • $length - сколько символов мы будем вырезать (по умолчанию будем вырезать все оставшиеся)
  • $encoding - кодировка

Теперь перейдем к примерам.

Получаем строку начиная с определенного символа

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, 8);
echo $result; 

// результат: phpstack.ru/admin/

Мы вырезали первые 8 символов из строки, содержащей URL адрес.

Получаем определенное количество символов

Теперь давайте вырежем еще и "/admin/" в конце.

Мы бы могли сделать это указав количество символов, которое нужно взять, оно равно количеству символов в домене, их 11

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, 8, 11); // возьмем 11 символов начиная с 8-го
echo $result; 

// результат: phpstack.ru

Вырезаем символы с конца

Что если мы не знаем количества символов в домене, но знаем что нужно вырезать строку "/admin/", длина которой составляет 7 символов? Иными словами нам нужно вырезать с конца.

В таком случае нужно указать отрицательное число:

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, 8, -7); // удаляем 8 символов с начала и 7 символов с конца
echo $result; 

// результат: phpstack.ru

Получаем несколько последних символов

Что если нам нужно вернуть наоборот только 7 последних символов? Тогда код будет следующим:

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, -7); // Получаем 7 символов с конца, остальное удаляем
echo $result; 

// результат: /admin/

Получаем первый символ строки

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, 0, 1); // Начиная с 0 берем 1 символ
echo $result; 

// результат: h

Получаем последний символ строки

$url = 'https://phpstack.ru/admin/';
$result = mb_substr($url, -1);  // начинаем на 1 символ относительно конца
echo $result; 

// результат: /

Получение подстроки по регулярному выражению

Если вам не хватает возможностей substr, возможно вам необходим более мощный инструмент: preg_match - эта функция позволяет получить подстроки по регулярному выражению.

Проблема при работе с многобайтовыми кодировками.

Рассмотрим такой пример:

$url = 'привет';
$result1 = mb_substr($url, 3); // удаляем 3 символа с начала
$result2 = substr($url, 3); // удаляем 3 символа с начала

var_dump($result1); // вет
var_dump($result2); // �ивет

Что случилось? Почему в первом случае, где мы использовали mb_substr все сработало хорошо, а во втором случае вернулся какой-то битый символ?

Дело в том, что в UTF-8 кириллица кодируется 2 байтам, вместо одного. substr считает, что символ равен байту и поэтому вырезает 3 байта с начала. Таким образом она вырезала букву "П", и только половину буквы "Р". В общем вы поняли: всегда используйте mb_substr когда работаете с текстом, который потенциально может содержать многобайтовые символы.

Продвинутая работа со строками

Если вы часто работаете со строками, вам пригодится это расширение: symfony/string

С его помощью вы сможете легко вырезать строки. Взгляните на несколько примеров:

// returns a substring which starts at the first argument and has the length of the
// second optional argument (negative values have the same meaning as in PHP functions)
u('Symfony is great')->slice(0, 7);  // 'Symfony'
u('Symfony is great')->slice(0, -6); // 'Symfony is'
u('Symfony is great')->slice(11);    // 'great'
u('Symfony is great')->slice(-5);    // 'great'

// reduces the string to the length given as argument (if it's longer)
u('Lorem Ipsum')->truncate(3);             // 'Lor'
u('Lorem Ipsum')->truncate(80);            // 'Lorem Ipsum'
// the second argument is the character(s) added when a string is cut
// (the total length includes the length of this character(s))
u('Lorem Ipsum')->truncate(8, '…');        // 'Lorem I…'
// if the third argument is false, the last word before the cut is kept
// even if that generates a string longer than the desired length
u('Lorem Ipsum')->truncate(8, '…', false); // 'Lorem Ipsum'

И это еще далеко не все.