Часто встречается необходимость обрезать строку, но не просто сделать это с помощью функции substr(), а так, чтобы сохранить слова целыми. Перед вами функция на PHP, которая позволяет разбивать строку по словам.
/**
* Обрезает строку до определённого количества символов не разбивая слова.
* @param string $str строка
* @param int $length длина, до скольки символов обрезать
* @param string $postfix постфикс, который добавляется к строке
* @return string обрезанная строка
*/
function cutStr($str, $length=50, $postfix='...')
{
if ( strlen($str) <= $length)
return $str;
$temp = substr($str, 0, $length);
return substr($temp, 0, strrpos($temp, ' ') ) . $postfix;
}
А вот версия для работы с многобайтовыми кодировками:
/**
* Обрезает строку до определённого количества символов не разбивая слова.
* Поддерживает многобайтовые кодировки.
* @param string $str строка
* @param int $length длина, до скольки символов обрезать
* @param string $postfix постфикс, который добавляется к строке
* @param string $encoding кодировка, по-умолчанию 'UTF-8'
* @return string обрезанная строка
*/
function mbCutString($str, $length, $postfix='...', $encoding='UTF-8')
{
if (mb_strlen($str, $encoding) <= $length) {
return $str;
}
$tmp = mb_substr($str, 0, $length, $encoding);
return mb_substr($tmp, 0, mb_strripos($tmp, ' ', 0, $encoding), $encoding) . $postfix;
}
У тебя будут проблемы с юникод строками — utf-8 это уже стандарт.
Для проверки можешь задать строку «Привет мир!». Визуально кажется, что символов 11, но фактически ее длина 22. Поэтому если написать cutStr(‘Привет мир!’, 11), то получится неожиданный результат =)
Тут надо работать с функциями из расширения mbstring
http://php.net/manual/ru/ref.mbstring.php
Точно! Я эту функцию писал давно, про mb_* знаю и активно использую)
Сейчас поправлю, благодарю за указание на ошибку!
Мое невежество, но давно хотел озадачиться вопросом многобайтовых кодировок.
На скорую руку у меня вот так вышло:
function cutString($str, $length, $postfix='...', $encoding=null) { $encoding = $encoding ?: mb_detect_encoding($str); if (mb_strlen($str, $encoding) <= $length) { return $str; } $tmp = mb_substr($str, 0, $length, $encoding); return mb_substr($tmp, 0, mb_strripos($tmp, ' ', 0, $encoding), $encoding) . $postfix; } $hw = 'Hello world!'; $hwRus = 'Привет мир!'; var_dump(cutString($hw, 7)); var_dump(cutString($hwRus, 8));Комментарии написали почти одновременно =)
Мне кажется в твоём варианте mb_detect_encoding() лишнее, проще указать ‘UTF-8’ в аргументе $encoding по-умолчанию.
А если у нас не utf-8? Либо мы изначально не знаем точно какая кодировка придет?
На самом деле я до конца не уверен в том, что функция mb_detect_encoding() корректно работает, хоть она и встроенная. Слишком много материала в гугле на тему «как определить кодировку строки» и там народ порой такие алгоритмы пишет, что глаза на лоб лезут от непонимания =)
Ну и потестируй еще мою, я до конца в ней не уверен =)
«На самом деле я до конца не уверен в том, что функция mb_detect_encoding() корректно работает, хоть она и встроенная.» — вот и я тоже не уверен. Лучше определить кодировку отдельно и передать её аргументом, а большинство случаев покрывает UTF-8 😉
Спасибо, мужик, все работает)
Коллеги
В задании было написано ЧТОБЫ СОХРАНЯЛИСЬ ЦЕЛЫМИ СЛОВА
поэтому дополняю скрипт
function cutString($str, $length, $postfix=’…’, $encoding=null) {
$encoding = $encoding ?: mb_detect_encoding($str);
if (mb_strlen($str, $encoding) <= $length) {
return $str;
}
while (mb_substr($str, $length, (1)) != ' ') {
// ДЛЯ ОТЛАДКИ РАСКОМЕНТИРУЙТЕ ЭТО echo $length++." ". mb_substr($str, 0, $length)."»;
// А ТО ЧТО НИЖЕ $length++ ЗАКОММЕНТИРУЙТЕ
$length++
if (mb_strlen($str, $encoding) <= $length) { return $str; }
}
$tmp = mb_substr($str, 0, $length, $encoding);
return mb_substr($tmp, 0, mb_strripos($tmp, ' ', 0, $encoding), $encoding) . $postfix;
}