Подстроки в PHP: проверка содержимого, выборка и замена
В этом материале поговорим о некоторых типичных задачах, которые могут возникать у PHP-разработчиков при работе со строковыми данными.
Рассмотрим мы 3 момента:
1. Как узнать, содержит ли строка искомую подстроку.
2. Как из более длинной строки "вытащить" определенную ее часть.
3. Как заменить часть строки другой строкой.
Все это - типовые задачи, которые (почти всегда) хорошо решаются встроенными средствами PHP.
Вводная
Перед тем, как начать, сразу условимся, что мы в принципе не работаем с однобайтными кодировками, т.е. кодировками, в которых каждый символ кодируется только одним байтом информации.
Типичным представителем однобайтных кодировок является, например, Windows-1251 (cp1251), а многобайтных - универсальная UTF-8.
Мы работаем исключительно с UTF-8 для того, чтобы соблюдать во всем принцип единообразия. Исходя из этого, мы всегда будем использовать строковые функции с префиксом "mb_", что означает "multibyte" - многобайтная.
Это позволит нам избежать проблем, которые точно будут возникать при попытке использовать классические строковые функции для обработки строк в кодировке UTF-8.
Кроме этого, следует отметить, что функциям с префиксом "mb_" можно передавать дополнительный необязательный аргумент - кодировку.
Я не очень рекомендую это делать, поскольку это придется проделывать с каждой строковой функцией, а это не очень удобно.
Гораздо проще задать нужную кодировку другим способом - через функцию mb_internal_encoding.
Если в каком-то файле вы работаете со строковыми функцими, то в начале файла (до вызова какой бы то ни было функции работы со строками) явно установите внутреннюю кодировку скрипта:
— Регулярная проверка качества ссылок по более чем 100 показателям и ежедневный пересчет показателей качества проекта.
— Все известные форматы ссылок: арендные ссылки, вечные ссылки, публикации (упоминания, мнения, отзывы, статьи, пресс-релизы).
— SeoHammer покажет, где рост или падение, а также запросы, на которые нужно обратить внимание.
SeoHammer еще предоставляет технологию Буст, она ускоряет продвижение в десятки раз, а первые результаты появляются уже в течение первых 7 дней. Зарегистрироваться и Начать продвижение
mb_internal_encoding("UTF-8");
Это позволит вам распространить действие кодировки UTF-8 на все функции данного скрипта.
1. Как узнать, содержит ли строка искомую подстроку
Допустим, перед нами стоит задача проверить email, который человек вводит в форму на сайте. Для того, чтобы хоть немного увеличить вероятность ввода корректного адреса, мы будем проверять, чтобы в электронном адресе обязательно был символ "@".
В этом нам поможет функция mb_strpos. Давайте посмотрим на нее в действии, подразумевая, что email человека мы получаем из глобального массива POST.
Для начала прописываем в скрипте уже рассмотренную нами функцию задания внутренней кодировки:
mb_internal_encoding("UTF-8");
После этого приступаем к нашей задаче:
if (mb_strpos($_POST['email'], '@') === false) { echo 'В адресе нет символа @'; }
Функция mb_strpos возвращает индекс первой позиции в строке при нахождении в ней заданной нами подстроки.
Если указанная нами подстрока в строке отсутствует, то будет возвращено значение false.
В частном случае, когда искомая подстрока входит в строку с самого начала, функция вернет нам значение 0, потому что индекс 0 соответствует первому символу в строке.
В этом случае может возникнуть вопрос: как же отличить, когда возвращаемое значение равно 0 (а значит вхождение подстроки найдено), а когда false (т.е. искомая подстрока в строке обнаружена не была).
Для решения этой задачи нужно использовать оператор тождественности (===) или нетождественности (!==) вместо другой пары операторов: равенства (==) и неравенства (!=).
В примере выше мы как раз используем оператор тождественности для того, чтобы стравнить с false возвращаемое функцией mb_strpos значение.
Таким образом, проверка будет проходить успешно (т.е. мы получим сообщение об отсутствии символа @) только в том случае, если mb_strpos вернет именно значение false, а не 0 или какое-то другое число.
Двигаемся дальше.
2. Как из более длинной строки "вытащить" определенную ее часть
Пусть перед нами стоит задача получить часть строки начиная с некой заранее заданной позиции. Допустим, мы хотим оперировать первыми 8 символами имени пользователя, которое он указал в регистрационной форме.
Для этой задачи логично использовать функцию mb_substr, имеющую следующий прототип:
$substring = mb_substr($string,$start,$length)
Первый аргумент - сама строка, с которой мы работаем. Второй - позиция, с которой мы "вытаскиваем" часть строки. Третий - длина получаемого фрагмента строки.
— Разгрузит мастера, специалиста или компанию;
— Позволит гибко управлять расписанием и загрузкой;
— Разошлет оповещения о новых услугах или акциях;
— Позволит принять оплату на карту/кошелек/счет;
— Позволит записываться на групповые и персональные посещения;
— Поможет получить от клиента отзывы о визите к вам;
— Включает в себя сервис чаевых.
Для новых пользователей первый месяц бесплатно. Зарегистрироваться в сервисе
В нашем случае для решения задачи мы напишем так:
$username = substr($_POST['username'],0,8);
Теперь посмотрим на различные варианты, которые могут быть.
1 вариант. Значения $start и $length положительны
В этом случае функция вернет нам $length символов строки, начиная с позиции $start. Не забываем, что первый символ строки имеет индекс 0.
echo mb_substr ('Как пройти в библиотеку?',11,7);
Результатом работы этого кода будет строка
в библи
2 вариант. Значение $length не указано
В этом случае функция вернет нам строку от $start до конца исходной строки.
echo mb_substr ('Как пройти в библиотеку?',18);
Результат будет следующим:
отеку?
3 вариант. Значение $start больше длины исходной строки
В этом случае функция просто вернет нам значение false.
4 вариант. $start в сумме с переменной $length выходит за конец строки
При таком раскладе функция mb_substr вернет нам всю оставшуюся часть строки.
echo mb_substr ('Как пройти в библиотеку?',13, 30);
Такой код вернет нам строку:
библиотеку?
5 вариант. Значение $start отрицательно
В этом случае функция будет вести отсчет не от начала, а от конца исходной строки.
echo mb_substr ('Как пройти в библиотеку?', -6); echo mb_substr ('Как пройти в библиотеку?', -20,6);
Результатом будут следующие строки соответственно:
отеку? пройти
6 вариант. Значение $start отрицательно и выходит за начало строки
Если значение $start равно, например, 30 при длине строки в 22 символа, функция ведет себя так, как если бы значение $start было равно 0.
7 вариант. Значение $length отрицательно
echo mb_substr ('Как пройти в библиотеку?', 4, -2); echo mb_substr ('Как пройти в библиотеку?', -20, -2);
В обоих случаях мы получим один и тот же результат:
пройти в библиотек
В первом случае мы делаем выборку с индекса 4 до позиции, отстоящей на 2 символа от конца строки.
Во втором случае мы начинаем выборку с позиции, отстоящей на 20 символов от конца строки до позиции, отстоящей на все те же 2 символа от конца строки.
3. Как заменить часть строки другой строкой?
Пусть перед нами стоит задача заменить некую часть строки другой подстрокой. К примеру, у нас есть номер банковской карты, в котором нужно скрыть (по сути - заменить) все цифры, кроме четырех последних.
По логике вещей мы должны были бы воспользоваться какой-нибудь строковой функцией с уже известным нам префиксом "mb_", обозначающим функции для работы с многобайтными кодировками.
Но не тут-то было!
Такой функции на момент написания данной статьи просто не существовало. Логично было бы ожидать, что есть штатная функция PHP под названием mb_substr_replace (производная от substr_replace), но ее нет.
Поэтому единственный выход - это создать или найти своеобразный "костыль", который позволит нам осуществить задуманное.
К счастью, народные умельцы уже все написали и представили на суд общественности вполне себе рабочую функцию под тем самым ожидаемым именем mb_substr_replace.
Поэтому для того, чтобы двигаться дальше, нам понадобится прописать ее в нашем PHP-файле:
function mb_substr_replace ($string, $replacement, $start, $length=null, $encoding=null) { if ($encoding == null) $encoding = mb_internal_encoding(); if ($length == null) { return mb_substr($string, 0, $start, $encoding) . $replacement; } else { if($length < 0) $length = mb_strlen($string, $encoding) - $start + $length; return mb_substr($string, 0, $start, $encoding) . $replacement . mb_substr($string, $start + $length, mb_strlen($string, $encoding), $encoding); } }
Теперь, когда функция определена, мы можем вызвать ее, передав наши параметры.
Давайте попробуем такой вариант:
echo mb_substr_replace('Моего брата зовут Николай, а сестру - Татьяна','Максим',18);
На выходе получим:
Моего брата зовут Максим
В этом примере мы заменяем все символы от позиции 18 и далее на строку "Максим", поэтому окончание строки затерто.
Следующий пример включает в себя дополнительный параметр $length, который говорит функции о том, что нужно заменить строго определенное число символов:
echo mb_substr_replace('Моего брата зовут Николай, а сестру - Татьяна','Максим',18,7);
На выходе получим:
Моего брата зовут Максим, а сестру - Татьяна
Как видите, в этом случае просто произошла замена имени Николай на Максим, а все остальное оставлено на своих местах.
Ок, с этими моментами разобрались. А как же наша банковская карта, где мы хотели заменить все цифры, кроме четырех последних? Давайте рассмотрим и этот пример.
$card_number = '1234 2222 2222 5111'; echo mb_substr_replace($card_number,'XXXX XXXX XXXX ',0, mb_strlen($card_number) - 4);
Сперва мы создаем переменную с номером банковской карты (такой подход нам пригодится при передаче 4 параметра нашей функции), после чего выводим номер карты, обработанный нужным нам образом.
Как видите, ничего необычного. Единственное, на что хочу обратить ваше внимание - это то, что в качестве 4 параметра (количество символов, которые нужно заменить) мы передаем результат работы функции mb_strlen по отношению к $card_number, уменьшенный на 4.
Функция mb_strlen высчитывает длину строки в символах. Зная эту длину, мы вычитаем из нее 4 символа (т.к. нам нужно заменить все, кроме 4 последних цифр карты).
Таким образом, все символы кроме 4 последних будут заменены большими буквами "X" - как раз то, что мы хотели.
Резльтатом выполнения данного кода будет следующая строка:
XXXX XXXX XXXX 5111
Вернемся теперь к предыдущему примеру и посмотрим, что будет, если значение параметра $length будет отрицательным:
echo mb_substr_replace('Моего брата зовут Николай, а сестру - Татьяна','Максим', -3);
При таком раскладе положение новой подстроки $replacement определяется отсчетом $start символов с конца исходной строки $string. Посмотрите на результат, чтобы понять, как это сработает:
Моего брата зовут Николай, а сестру - ТатьМаксим
Другая разновидность этого случая выглядит так:
echo mb_substr_replace('Моего брата зовут Николай, а сестру - Татьяна','Максим', -30,3);
Результатом будет такой вывод:
Моего брата зовМаксимНиколай, а сестру - Татьяна
С первого взгляда можно не понять, поэтому немного поясню. Берется вся исходная строка, и строка замены вставляется на позицию, отстоящую на 30 символов назад от конца исходной строки.
В нашем случае строка замены "Максим" вставляется после "Моего брата зов". Слово "Максим" заменяет собой 3 символа - "ут " (у,т и символ пробела), после чего продолжается исходная строка "Николай, а сестру - Татьяна".
Теперь, думаю, все точно встало на свои места.
Как вы понимаете, сфера применения данной функции достаточно широка, но обычно ее используют для сокращения текста слишком длинного для вывода.
Как вариант, можно вывести часть текста и создать ссылку на его полную версию (этот принцип используется для создания анонсов статей).
Рассмотрим гипотетический пример кода, который мог бы выводить первые 50 символов статьи, за которыми следует слово "Дальше" и многоточие, являющиеся ссылкой на страницу для вывода полной версии статьи:
$link = mysqli_connect("localhost", "my_user", "my_password", "world"); $res = mysqli_query($link, "SELECT id, message FROM messages WHERE id = $id") or die(); $obj = mysqli_fetch_object($res); printf('<a href="more-text.php?id=%d">%s</a>', $obj->id, mb_substr_replace($obj->message,' Дальше...',50));
Понятно, что пример сильно упрощенный, но наша задача здесь - не работа с базой данных, а рассмотрение вариантов применения строковых функций, поэтому не будем углубляться в совершенно другую тему.
Ну что ж, вот мы и разобрали три основных момента, которые были в нашем плане:
1. Научились узнавать, содержит ли строка искомую подстроку.
2. Научились "вытаскивать" из строки опредленную ее часть.
3. Разобрались с тем, как заменять часть строки другой подстрокой.
Надеюсь, что данный мтериал был для вас полезен. Если да, то поделитесь им с коллегами и друзьями.
Спасибо, и до связи!
Дмитрий
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также: