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

Красавчег

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

PHP:
// Shorten string function
function shortenStr ($str, $len) {
    return strlen($str) > $len ?  substr($str, 0, $len)."…" : $str;
}

Сам сайт в кодировке UTF-8, а описание в базе в кодировке cp1251_general_ci

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

HTML:
тексттексттексттексттекст�…

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

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

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

PHP:
function shortenStr ($str, $len) { 
    return mb_strlen($str,"UTF-8") > $len ?  mb_substr($str, 0, $len,"UTF-8")."…" : $str; 
}

И для работы с utf смотрите в сторону функций mb_...
 
лучше обрезать правильно до конца слова, а не слово поплам.

Код:
<?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);
  }

}

?>
 
по поводу обрезки по словам согласен с XSiteCMS - дело в том, что в utf на один символ используется 2 байта, и если обрезается на так называемом "служебном" байте, то на выходе как раз будет
тексттексттексттексттекст�
а вот по поводу реализации...

XSiteCMS, а зачем так усложнять? - если можно просто взять кол-во пробелов в строке - кол-во пробелов и будет кол-вом слов
 
по поводу обрезки по словам согласен с XSiteCMS - дело в том, что в utf на один символ используется 2 байта, и если обрезается на так называемом "служебном" байте, то на выходе как раз будет
а вот по поводу реализации...
XSiteCMS, а зачем так усложнять? - если можно просто взять кол-во пробелов в строке - кол-во пробелов и будет кол-вом слов
Дополню чуток, предварительно необходимо будет бахнуть вхождение более одного пробела идущих подряд в строке.
 
Вариант от XSiteCMS с обрезкой текста в конце слова, конечно лучше и симпатичнее, но если его применять в достаточно больших текстовых блоках.

В моём же случае я выбрал вариант от Monterpan, так как у меня текстовые блоки очень маленькие и нужно в блок вместить именно определённое кол-во символов.
 
t3s, часть функция используется в других классах поэтому может показатся грамозсдко, но для этой функции используется несколько простых функций. просто разнесены для удобства.

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

ПС: для работы с УТФ заменить substr на mb_substr
 
Назад
Сверху