Подскажите, плз, как обрезать текст, задав максимальное количество символов, но при этом не обрезая слова. Нужно сделать анонс новости на главной странице (кусок текста новости).
наверное как-то так: $максимальное кол-во символов = 100; $строка = substr($строка, 0, $максимальное кол-во символов); $конец строки = strlen(строка); пока (строка[$конец строки] !== " "){ $строка = substr($строка, 0, strlen($строка)-1) } echo $str . "...";
не, этот вариант плохой.. лучше так: (хотя и криво, понимаю...) PHP: <?php Error_Reporting(E_ALL & ~E_NOTICE); $max = 50; $str = 'новость дня новость дняновость дняновостьдняновость дняновостьдняновостьдня'; echo "исходная строка: <br>" . $str . "<br>"; $n = strlen($str); $m = 0; while ($str[$n] !== " ") { $m+=1; $n-=1; }; $str = substr($str,0,strlen($str)-$m); echo "обрезанная строка: <br>" . $str; ?>
самый правильный подход - завести поле "анонс" и вписыывать туда нужный текст... учить до просветления. http://www.artlebedev.ru/kovodstvo/98/
О! Холивар! Я против дубляжа текста при наборе. (Но не против - в базе) Предлагаю ставить метку в основном тексте, откусывать анонс и класть в базу.
Пишете ваш длинный текст, неожиданно в середине ставите какой-нибудь символ/комбинацию, при выводе в анонс - отрываете кусок до нее, при выводе куда надо - удаляете символ/комбинацию. Это если весь текст хранить в одной ячейке таблицы БД. Или же поступаете аналогично, при наборе текста точно так же указываете метку, при нажатии кнопки "Отправить/Послать/Что-там-еще" отгрызаете все до метки - это заносится в столбец "анонс", а все, что после метки, заносите в другой столбец. При выводе анонса выбираете из таблицы только анонс, при выводе всего текста - анонс + текст, соединяете их и выводите в удобном вам виде. Или не соединяете, тут уже все в ваших руках. И никакого дублирования в процессе.
Вариант попроще - брать первый параграф. Вариант посложнее - сделать какой либо тег разметки для откусывания. + еще и для формирования текста на полную новость.
Спасибо, тоже попробую. Кажется, нашла простой выход: PHP: <?php $str = "Темпы роста рынка электронных платежных систем России замедлились в 2006 г."; echo "ИЗНАЧАЛЬНАЯ СТРОКА: " . $str . "<br><br>"; $length = 20; // Максимальная длина обрезанной строки do { substr($str,$length,1); $length = $length - 1; } while (substr($str,$length,1) !== " "); $str_cut = substr($str,0,$length); echo "ОБРЕЗАННАЯ СТРОКА: " . $str_cut; ?>
будем уважать своих посетителей или пофиг - все равно прочтут? это как ссылки делать в новостях. или выделять весь параграф или помечать отдельные слова в заголовке.
PHP: <?php define ('MAX_WIDTH', 20); $str = "тут такая строка очень длинная..."; if (strlen ($str) > MAX_WIDTH) $str = substr ($str, 0, MAX_WIDTH-strlen (strrchr (substr ($str, 0, MAX_WIDTH), ' '))); echo "#$str#"; ?> как-то вот так получилось... 4 вызова... можно ещё попробовать с wordwrap, но это в качестве самостоятельного упражнения.
А тем временем, Дима Смирнов рулит аж с 1998-ого года . PHP: $txt = 'Переменная с текстом'; preg_match("/.{150}[^.!;?]*[.!;?]/si", $txt.". ", $matches); $txt=$matches[0];
может так.. PHP: <?php echo implode(array_slice(explode('<br>',wordwrap($text,$lenght,'<br>',false)),0,1)); ?> собственно, алгоритм работы: 1) wordwrap без разделения слов разбивает строку $text на элементы длиной $lenght с разделителем '<br>'. 2) explode разбивает полученную на этапе 1 строку на массив по элементу <br> 3) array_slice из полученного массива возвращает массив, состоящий из элементов исходного, начиная с 0, в кол-ве 1, то есть первую строку. 4) implode выпрямляет полученный массив с 1 элементом в строку 5) echo выплевывает строку в поток вывода.
ну, где-то так. только если по-хорошему делать, $text надо ещё предварительно пропустить через htmlspecialchars, чтобы убрать маркер (если в тексте уже есть <br>, он собьёт разделение). по-любому, не менее четырёх вызовов, из которых три -- на массивах.
lexa принцип ясен, но это немного не то. в вашем с димой случае вы получаете предложение (строку, оканчивающуюся символами .!;?), длиной не менее 150 символов. задача ставилась немного другая. используя реги я бы на вашем с димой месте написал так: /^.{,150}\W/
стоят ли все эти "програмистские изыски" одно поля в табличке и такого же в форме куда знающий редактор/оперетор поместит именно тот текст, который наиболее подходит и по размеру и по содержанию? ИМХО - нет. ИМХО муйней маетесь товарищи.
440Hz а если этого поля нет? например, вы получаете новостную строку и хотите отобразить только её начало?
в общем так. зацепило меня этим примером. решил поэкспериментировать. сделал замеры. и вот что у меня нарисовалось (я позволил себе чуток модифицировать приведённые примеры дабы выжать из них по максимуму). постановка задачи определить относительную производительность четырёх предложенных вариантов решения задачи об усечении длинной строки по границе слова. производительность замеряется относительно операции присваивания данной строки локальной переменной. итак строка (375 символов): Код (Text): $str = 'Here we got a very very long string which is repeated multiple times to produce a more native look of a news line paragraph. Here we got a very very long string which is repeated multiple times to produce a more native look of a news line paragraph. Here we got a very very long string which is repeated multiple times to produce a more native look of a news line paragraph.'; эталонный код: Код (Text): $a = $str; код №1 (принцип -- вручную ищем первый пробел в строке начиная с позиции MAX_WIDTH по направлению к началу): Код (Text): for ($length = MAX_WIDTH ; $str[$length] !== ' ' and $length ; $length-- ); $a = substr ($str, 0, $length); код №2 (принцип -- делаем то же самое, но при помощи встроенных функций): Код (Text): $a = substr ($str, 0, MAX_WIDTH-strlen (strrchr (substr ($str, 0, MAX_WIDTH), ' '))); код №3 (принцип -- используя встроенную функцию wordwrap делим строку, ограничивая подстроки маркером. после этого при помощи explode извлекаем первую подстроку. перед вызовом wordwrap удаляем лишнее, чтобы не хранить слишком много такста): Код (Text): list ($a) = explode ('<br>', wordwrap (substr ($str, 0, MAX_WIDTH+1), MAX_WIDTH, '<br>', false)); код №4 (регулярка берёт первые MAX_WIDTH символов от начала строки и откатывается назад до первого не-буквенного символа): Код (Text): preg_match ('/^.{0,'.MAX_WIDTH.'}\W/', $str, $matches); $a = substr ($matches[0], 0, -1); итоги конкурса: Код (Text): bench name: wordwrap first N characters empty : 1.00 snippet1: 6.17 snippet2: 5.70 snippet3: 8.27 snippet4: 8.85 total time: 21.19 sec. php ver: 4.4.7 os: Darwin или если выражаться картинно: Код (Text): 0: * 1: ****** 2: *****- 3: ********- 4: ********* выводы: 1/ разброс значений не такой уж и большой. несмотря на то, что регулярка (самое тяжёлое решение) в полтора раза тяжелее кода №2 я склоняюсь к тому, что в скромном проекте (не требующем выжимать максимума из кода) использовать надо именно её, потому как нагляднее. 2/ приятно порадовал код №1 с ручным поиском. твёрдое второе место по производительности. при желании могу выложить код для замера производительности дабы не быть голословным