Обрезание строки текста до заданного предела?

Тема в разделе "PHP", создана пользователем Красавчег, 16 авг 2011.

Модераторы: latteo
  1. Красавчег

    Красавчег Завсегдатай

    Регистр.:
    15 мар 2010
    Сообщения:
    902
    Симпатии:
    298
    В движке есть фукция, которая обрезает описание (текст) до заданного кол-ва символов:

    PHP:
    // Shorten string function
    function shortenStr ($str$len) {
        return 
    strlen($str) > $len ?  substr($str0$len)."…" $str;
    }
    Сам сайт в кодировке UTF-8, а описание в базе в кодировке cp1251_general_ci

    Так вот, проблема в том, что после обрезания текст на странице выглядит следующим образом:

    HTML:
    тексттексттексттексттекст�…
    Как мне избавиться от хрени которая выделена красным цветом?

    тексттексттексттексттекст

    п.с. кодировку описания в базе поменять не могу, потому что тогда начинает весь движок глючить.
     
  2. Monterpan

    Monterpan Постоялец

    Регистр.:
    3 мар 2008
    Сообщения:
    150
    Симпатии:
    27
    Используйте

    PHP:
    function shortenStr ($str$len) { 
        return 
    mb_strlen($str,"UTF-8") > $len ?  mb_substr($str0$len,"UTF-8")."…" $str
    И для работы с utf смотрите в сторону функций mb_...
     
    Красавчег нравится это.
  3. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    лучше обрезать правильно до конца слова, а не слово поплам.

    Код:
    <?php
    
    /**
     * $Revision: 507 $
     * $Author: CrashX $
     * $Date: 2010-02-02 14:27:01 +0600 (Вт, 02 фев 2010)$
     * $LastChangedDate: 2011-04-18 11:02:24 +0700 (Пн, 18 апр 2011) $
     * $Id: string.php 507 2011-04-18 04:02:24Z CrashX $
     * Copyright © CrashX <XSiteCMS@gmail.com>
     * Всі права захищено © CrashX
     */
    if (!defined('_SHELL'))
      die();
    
    /**
     * Класс Работы со строками
     */
    class String {
    
      var $version = 0.01;
      private $data = null;
      private $symbol = array(
          "'", '"', "`", "«", "»",
          "(", ")", "[", "]", "{", "}", "<", ">",
          "~", "@", "#", "№", "$", "%", "^", "&",
          "*", "_", "+", "-", "=",
          ",", ".", "!", "?", ";", ":",
          "|", "\"", "\\", "/",
          "\r\n", "\n", "\t", "¬",
          "\x27", "\x22", "\x60", "x0B", "\0",
          " "
      );
      //private $xss = array();
    
      /**
       * Сравнивание строк, учетом регистра или без него
       * @param string
       * @param string
       * @param boolean
       * @return boolean
       */
      function compare($that, $what, $caps=false) {
    //Возвращает < 0, если that меньше what > 0, если that больше what, и 0, если они равны.
        if ($caps):
          if (!strcasecmp($that, $what)):
            return true;
          endif;
        else:
          if ($that === $what):
            return true;
          endif;
        endif;
        return false;
      }
    
      /**
       * Умная обрезка строк до конца слов, по указанной длине
       * @param string
       * @param integer
       * @return string
       */
      function cut($string, $length=450) {
        if ($this->length($string) > $length):
          $string = $this->substring($string, 0, $length - ($this->length($this->last($this->substring($string, 0, $length), " "))));
          return $string . " ...";
        endif;
        return $string;
      }
    
      /**
       * Удаление символов переноса, возврата каретки, табуляции и слешей "\"
       * @param string
       * @return string
       */
      function trim($string) {
        $string = trim($string); // работает когда хочет ((
        preg_replace("/\s+/", " ", $string); // удаляем двойные пробелы
        $search = array("\n", "\r", "\t"); // выносим все лишнее
        $replace = array("", "", "");
        $string = str_replace($search, $replace, $string);
        $string = stripslashes($string);
        return $string;
      }
    
      /**
       * Очистка строки
       * @param string
       * @return string
       */
      function clean($string) {
        $this->tag($string);
        $string = str_replace($this->symbol, " ", $string);
        $this->trim($string);
        return $string;
      }
    
      function tag($string) {
        $string = preg_replace("#\<.+?\>|</.+?\>#is", " ", $string);
        $string = preg_replace('/<br.*?>/is', "\n", $string);
        $search = array(
            '@<script[^>]*?>.*?</script>@si', // Strip out javascript
            '@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
            '@<style[^>]*?>.*?</style>@siU', // Strip style tags properly
            '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments including CDATA
        );
        $string = preg_replace($search, '', $string);
        return $this->trim($string);
      }
    
      function divide($array, $min=6, $max=15) {
        $words = array();
        reset($array);
        foreach ($array as $string):
          if ($this->length($string) >= $min && $this->length($string) <= $max):
            $words[] = $string;
          endif;
        endforeach;
        $array = $words;
        unset($words);
        return $array;
      }
    
      function length($string) {
        return mb_strlen($string);
      }
    
      function last($string, $offset, $part = null) {
        return mb_strrchr($string, $offset, $part);
      }
    
      function substring($string, $offset, $length = null) {
        return mb_substr($string, $offset, $length);
      }
    
      /**
       * Перевод в нижний регистр
       * @param string
       * @return string
       */
      function lower($str) {
        return mb_strtolower($str);
      }
    
      /**
       * Перевод в нижний регистр
       * @param string
       * @return string
       */
      function upper($str) {
        return mb_strtoupper($str);
      }
    
      /**
       * Перевод в нижний регистр
       * @param string
       * @return string
       */
      function zsplit($str) {
        return preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
      }
    
    }
    
    ?>
    
     
    Красавчег нравится это.
  4. t3s

    t3s

    Регистр.:
    16 фев 2008
    Сообщения:
    719
    Симпатии:
    290
    по поводу обрезки по словам согласен с XSiteCMS - дело в том, что в utf на один символ используется 2 байта, и если обрезается на так называемом "служебном" байте, то на выходе как раз будет
    а вот по поводу реализации...

    XSiteCMS, а зачем так усложнять? - если можно просто взять кол-во пробелов в строке - кол-во пробелов и будет кол-вом слов
     
  5. trooll

    trooll PHP кодер

    Регистр.:
    22 дек 2008
    Сообщения:
    503
    Симпатии:
    116
    Дополню чуток, предварительно необходимо будет бахнуть вхождение более одного пробела идущих подряд в строке.
     
  6. Красавчег

    Красавчег Завсегдатай

    Регистр.:
    15 мар 2010
    Сообщения:
    902
    Симпатии:
    298
    Вариант от XSiteCMS с обрезкой текста в конце слова, конечно лучше и симпатичнее, но если его применять в достаточно больших текстовых блоках.

    В моём же случае я выбрал вариант от Monterpan, так как у меня текстовые блоки очень маленькие и нужно в блок вместить именно определённое кол-во символов.
     
  7. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    t3s, часть функция используется в других классах поэтому может показатся грамозсдко, но для этой функции используется несколько простых функций. просто разнесены для удобства.

    просто у меня там можно искать было до конча предложение, но потом этот код оказался невалдиным (, тк много потреблял процессорного времение и памяти (
     
  8. maniche

    maniche Писатель

    Регистр.:
    7 авг 2011
    Сообщения:
    6
    Симпатии:
    1
    Я думаю вариант из смарти выглядит более симпатично да и работает шустрее
    http://www.8tiny.com/source/oxideshop/nav.html?core/smarty/plugins/modifier.truncate.php.source.html
    ПС: для работы с УТФ заменить substr на mb_substr