PHP: str_replace - замена или удаление подстроки в строке

Функция str_replace в php нужна для замены подстроки в строке.

У функции следующие параметры:

$result = str_replace('что меняем', 'на что меняем', 'в чем меняем');

Замена подстроки

Пример: заменим bbb на zzz:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace('bbb', 'zzz', $str); 

echo $result; // результат: aaa zzz ccc zzz ddd

Мы заменили "bbb" на "zzz" и в $result запишется строка "aaa zzz ccc zzz ddd". У нас было 2 вхождения подстроки bbb и мы заменили их на zzz.

А что если нам нужно также заменить и ccc на zzz? Мы бы конечно могли запустить функцию 2 раза, в первый раз заменив первую подстроку, а второй раз другую, но можно просто указать массив подстрок поиска первым параметром.

Пример: заменим bbb и ccc на zzz:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace(['bbb', 'ccc'], 'zzz', $str); 

echo $result; // результат:  aaa zzz zzz zzz ddd

Что если нам нужно заменить bbb на zzz, а ccc на www?

Мы конечно снова можем запустить функцию 2 раза, но оптимальнее с точки зрения производительности будет и вторым параметром передать массив. В первом массиве будут подстроки, которые мы ищем, а во втором те, на которые заменяем.

Пример: заменяем bbb на zzz, а ccc на www:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace(['bbb', 'ccc'], ['zzz', 'www'], $str); 

echo $result; // результат:  aaa zzz www zzz ddd

Результат у нас правильный, но читабельность конечно страдает. А представьте если бы мы указывали сразу 50 таких строк для замены? И потом когда мы добавляем или заменяем строку, ее приходилось бы искать в 2 местах.

Более читабельным был бы код:

$str = 'aaa bbb ccc bbb ddd';

$replaces = [
    'bbb' => 'zzz',
    'ccc' => 'www',
];

$result = str_replace(array_keys($replaces), array_values($replaces), $str);

echo $result; // результат:  aaa zzz www zzz ddd

Тут нам помогли функции array_keys и array_values которые вернули все ключи и все значения соответственно. Кстати для подобной замены вам не обязательно использовать функцию str_replace, а можно воспользоваться strtr, и тогда наш код выглядел бы еще более просто:

$str = 'aaa bbb ccc bbb ddd';

$result = strtr($str, [
    'bbb' => 'zzz',
    'ccc' => 'www',
]);

echo $result; // результат:  aaa zzz www zzz ddd

У функции str_replace также есть четвертый параметр $count, в котором мы ничего не передаем, а наоборот получаем количество вхождений.

Таким образом если дополнить наш пример:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace('bbb', 'zzz', $str, $count); 

echo $result; // результат: aaa zzz ccc zzz ddd

echo 'Вхождений: ' . $count; //  Вхождений: 2

Обязательно прочитайте подробную документацию: https://www.php.net/manual/ru/function.str-replace.php

Удаление подстроки

Хоть это и очевидно, давайте проговорим еще момент с удалением строк. Чтобы удалить подстроку нужно просто заменить ее на пустоту (пустую строку).

Удалим xx из нашей строки:

str_replace('xx', '', 'aa xx bb'); // вторым параметром у нас идет пустая строка.

Другие примеры

Рассмотрим еще несколько примеров:

// Порядок замены
$str     = "Строка 1\nСтрока 2\rСтрока 3\r\nСтрока 4\n";
$order   = array("\r\n", "\n", "\r");
$replace = '<br />';

// Обрабатывает сначала \r\n для избежания их повторной замены.
echo $newstr = str_replace($order, $replace, $str);

// Выводит F, т.к. A заменяется на B, затем B на C, и так далее...
// В итоге E будет заменено F, так как замена происходит слева направо.
$search  = array('A', 'B', 'C', 'D', 'E');
$replace = array('B', 'C', 'D', 'E', 'F');
$subject = 'A';
echo str_replace($search, $replace, $subject);

// Выводит: яблорехкорех орех (по вышеуказанной причине)
$letters = array('я', 'о');
$fruit   = array('яблоко', 'орех');
$text    = 'я о';
$output  = str_replace($letters, $fruit, $text);
echo $output;

Эта функция не поддерживает регулярные выражения, но для этого есть другая функция: preg_replace()

Более мощная альтернатива: preg_replace

С помощью функции preg_replace вы можете осуществлять замену по регулярном выражению. Если вам не хватает возможностей str_replace, то обратите внимание на эту функцию.

Ссылка на документацию: https://www.php.net/manual/ru/function.preg-replace.php

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

Если вы часто работаете со строками, то возможно вам пригодятся более высокоуровневые методы для их обработки.

Взгляните как будут выглядеть поиск и замена строк с помощью symfony/string:

// checks if the string starts/ends with the given string
u('https://symfony.com')->startsWith('https'); // true
u('report-1234.pdf')->endsWith('.pdf');        // true

// checks if the string contents are exactly the same as the given contents
u('foo')->equalsTo('foo'); // true

// checks if the string content match the given regular expression
u('avatar-73647.png')->match('/avatar-(\d+)\.png/');
// result = ['avatar-73647.png', '73647']

// checks if the string contains any of the other given strings
u('aeiou')->containsAny('a');                 // true
u('aeiou')->containsAny(['ab', 'efg']);       // false
u('aeiou')->containsAny(['eio', 'foo', 'z']); // true

// finds the position of the first occurrence of the given string
// (the second argument is the position where the search starts and negative
// values have the same meaning as in PHP functions)
u('abcdeabcde')->indexOf('c');     // 2
u('abcdeabcde')->indexOf('c', 2);  // 2
u('abcdeabcde')->indexOf('c', -4); // 7
u('abcdeabcde')->indexOf('eab');   // 4
u('abcdeabcde')->indexOf('k');     // null

// finds the position of the last occurrence of the given string
// (the second argument is the position where the search starts and negative
// values have the same meaning as in PHP functions)
u('abcdeabcde')->indexOfLast('c');     // 7
u('abcdeabcde')->indexOfLast('c', 2);  // 7
u('abcdeabcde')->indexOfLast('c', -4); // 2
u('abcdeabcde')->indexOfLast('eab');   // 4
u('abcdeabcde')->indexOfLast('k');     // null

// replaces all occurrences of the given string
u('http://symfony.com')->replace('http://', 'https://'); // 'https://symfony.com'
// replaces all occurrences of the given regular expression
u('(+1) 206-555-0100')->replaceMatches('/[^A-Za-z0-9]++/', ''); // '12065550100'
// you can pass a callable as the second argument to perform advanced replacements
u('123')->replaceMatches('/\d/', function ($match) {
    return '['.$match[0].']';
}); // result = '[1][2][3]'

Как видите здесь есть много полезных методов, для написания которых мы с вами могли бы потратить много времени. Посмотрите также другие полезные примеры работы с symfony/string