За последние 24 часа нас посетили 17648 программистов и 1671 робот. Сейчас ищут 1498 программистов ...

Функция обрезки текста по словам

Тема в разделе "PHP для новичков", создана пользователем salesBT, 22 дек 2017.

  1. salesBT

    salesBT Активный пользователь

    С нами с:
    18 дек 2014
    Сообщения:
    10
    Симпатии:
    0
    Привет всем!!
    Имеется функция обрезки текста по словам:

    PHP:
    1. function my_cut($string, $length){
    2. $string = mb_substr($string, 0, $length,'UTF-8'); // обрезаем и работаем со всеми кодировками и указываем исходную кодировку
    3. $position = mb_strrpos($string, ' ', 'UTF-8'); // определение позиции последнего пробела. Именно по нему и разделяем слова
    4. $string = mb_substr($string, 0, $position, 'UTF-8'); // Обрезаем переменную по позиции
    5. return $string;
    6. $text = 'Северная война закончилась в 1721 году';
    7. echo my_cut($text, 17); // выведет 'Северная война', без части слова 'закончилась'
    она работает только в том случае если $length (значение 17) меньше всех символов в переменной $text. Если у $length значение поменять на 50, например, то выводит только первое слово - "Северная". А нужно, чтоб выводило полностью "Северная война закончилась в 1721 году"

    Подскажите пожалуйста, как это исправить?
     
  2. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    просто добавь в начало функции
    PHP:
    1. if ($length >= mb_strlen($string, 'UTF-8'))
    2.     {
    3.         return $string;
    4.     }
    и будет выводить фарзу целиком. Повторить вывод только первого слова у меня так и не получилось.
     
    salesBT нравится это.
  3. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    Я использую подобную функцию:
    PHP:
    1. function short_text($text, $len = 200)
    2.     {
    3.         $tarr = explode(' ', $text);
    4.         $txt = '';
    5.         $i = 0;
    6.         while (mb_strlen($txt) < $len && isset($tarr[$i]))
    7.         {
    8.             $txt .= $tarr[$i] . ' ';
    9.             $i++;
    10.         }
    11.         return $txt;
    12.     }
     
  4. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    @Maputo то есть допускаешь итоговую строку длиннее чем ограничение параметром len? И пробел в конце ещё шумит.
     
  5. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    @Ganzal, да. Я изначально делал функцию с итоговой длиной меньше $len, но потом понял, что на практике игра не стоит свеч.
     
  6. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    @Maputo, Ну ровно так же как ты в каждой итерации проверяешь текущую длину результирующей строки - ты можешь проверять сумму /длины строки, единицы, и длины текущего фрагмента в буфере/ на выход за пределы допустимой длины. И прерывать цикл если добавление будет лишним. Ну это так. Вариация алгоритма. А пробел таки лишний. :cool:
     
  7. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @salesBT, вот вариант:
    PHP:
    1. function my_cut($string, $length) {
    2.     $strlen = mb_strlen($string);
    3.     if($strlen <= $length) {
    4.         return $string;
    5.     }
    6.     $string2 = mb_substr($string, 0, $length, 'UTF-8'); // обрезаем и работаем со всеми кодировками и указываем исходную кодировку
    7.     $position = mb_strrpos($string2, ' ', 'UTF-8'); // определение позиции последнего пробела в урезанной строке. Именно по нему и разделяем слова
    8.     if($position === false) { // если нет пробелов
    9.         $position = mb_strpos($string, ' ', 0, 'UTF-8'); // ищем позицию первого в исходной строке
    10.     }
    11.     $string = mb_substr($string, 0, $position, 'UTF-8'); // Обрезаем переменную по позиции
    12.     return $string;
    13. }
    14. $text = 'Северная война закончилась в 1721 году';
    15. echo my_cut($text, 5); // выведет 'Северная'
    16. echo '<br>';
    17. echo my_cut($text, 17); // выведет 'Северная война'
    18. echo '<br>';
    19. echo my_cut($text, 50); // выведет всю фразу
     
    salesBT нравится это.
  8. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    Была такая версия (менее требуемой длины и без лишнего пробела):
    PHP:
    1. function short_text($text, $len = 200)
    2.     {
    3.         $tarr = explode(' ', $text);
    4.         $txt = '';
    5.         $i = 0;
    6.         while (mb_strlen($txt) < $len && isset($tarr[$i]))
    7.         {
    8.             $txt .= $tarr[$i] . ' ';
    9.             $i++;
    10.         }
    11.         return implode(' ', array_slice($tarr, 0, $i - 1));
    12.     }
    Вобщем давно это было - надо еще проверить функцию...
     
    #8 Maputo, 22 дек 2017
    Последнее редактирование: 22 дек 2017
  9. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    @Maputo зачем тратить время на конкатенацию строки, если можно инкрементить некий счетчик на длину текущего фрагмента буфера плюс пробельную единицу?
     
    Maputo нравится это.
  10. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    @Ganzal, да. Так будет быстрее работать. Согласен.
    PHP:
    1.     function short_text($text, $len = 200)
    2.     {
    3.         $tarr = explode(' ', $text);
    4.         $txt = 0;
    5.         $i = 0;
    6.         while ($txt < $len && isset($tarr[$i]))
    7.         {
    8.             $txt += mb_strlen($tarr[$i]) + 1;
    9.             $i++;
    10.         }
    11.         return implode(' ', array_slice($tarr, 0, $i - 1));
    12.     }
     
    #10 Maputo, 22 дек 2017
    Последнее редактирование: 22 дек 2017
  11. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @salesBT, ещё есть mb_strimwidth, которая обрежет строку до заданного размера и добавит вместо откинутого хвоста указанные в параметрах символы. Не по пробелам (целым словам), конечно, но тоже хороша :)
     
  12. salesBT

    salesBT Активный пользователь

    С нами с:
    18 дек 2014
    Сообщения:
    10
    Симпатии:
    0
    Большое спасибо всем!
    Добавил многоточие в конце при обрезке текста:
    PHP:
    1. return $string . ' . . .';
    В итоге получилось то, что нужно:

    PHP:
    1. function my_cut($string, $length) {
    2.     $strlen = mb_strlen($string, 'UTF-8');
    3.    
    4.     if($strlen <= $length) {
    5.        return $string;
    6.    
    7.     }
    8.     $string2 = mb_substr($string, 0, $length, 'UTF-8'); // обрезаем и работаем со всеми кодировками и указываем исходную кодировку
    9.     $position = mb_strrpos($string2, ' ', 'UTF-8'); // определение позиции последнего пробела в урезанной строке. Именно по нему и разделяем слова
    10.     if($position === false) { // если нет пробелов
    11.         $position = mb_strpos($string, ' ', 0, 'UTF-8'); // ищем позицию первого в исходной строке
    12.     }
    13.     $string = mb_substr($string, 0, $position, 'UTF-8'); // Обрезаем переменную по позиции
    14.     return $string . ' . . .';
    15. }
    16.  
    17. $text = 'Северная война закончилась в 1721 году';
    18. echo my_cut($text, 17);
     
  13. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @salesBT, вот другой вариант:
    PHP:
    1. function my_cut2($str, $len) {
    2.     if($len >= mb_strlen($str)) {
    3.         return $str;
    4.     }
    5.     $arr = [];
    6.     $pattern = '/^.{1,'.$len.'}(?=\s|$)|^.+?(?=\s|$)/u';
    7.     preg_match($pattern, $str, $arr);
    8.     return (empty($arr[0]) ? '' : $arr[0]).'&hellip;';
    9. }
    10. $text = 'Северная война закончилась в 1721 году';
    11. echo my_cut2($text, 5).'<br>';
    12. echo my_cut2($text, 17).'<br>';
    13. echo my_cut2($text, 27).'<br>';
    14. echo my_cut2($text, 30).'<br>';
    15. echo my_cut2($text, 37).'<br>';
    16. echo my_cut2($text, 50).'<br>';
    --- Добавлено ---
    Кстати, как поступать с фразой из единственного слова?
    --- Добавлено ---
    если хотим, допустим, получить три буквы из фразы "Северная"?
     
    #13 Sail, 22 дек 2017
    Последнее редактирование: 22 дек 2017
  14. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    Я использую функцию примерно вида такого:
    PHP:
    1. public static function cut_utf($str, $length)
    2.     {
    3.         $strlength = mb_strlen($str, "utf8");
    4.         $str = ($strlength > $length) ? mb_substr($str, 0, $length, "UTF-8")."..." : $str;
    5.         return $str;
    6.     }
     
  15. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.593
    Симпатии:
    362
    @_ne_scaju_, у ТС фишка с нежеланием выводить огрызок слова, попадающего под секвестр...