Как усечь строку в PHP до слова, ближайшего к определенному количеству символов?

У меня есть фрагмент кода, написанный на PHP, который извлекает блок текста из базы данных и отправляет его в виджет на веб-странице. Исходный блок текста может быть длинной статьей или коротким предложением или двумя; но для этого виджета я не могу отображать больше, скажем, 200 символов. Я мог бы использовать substr (), чтобы отрезать текст на 200 символов, но результат был бы обрезан посередине слов - что я действительно хочу, так это отрезать текст в конце последнего слово перед 200 символами.

Вопрос предназначен для того, чтобы сказать, что усеченный текст уместится в некотором фиксированном количестве пикселей на веб-странице. В этом случае, в зависимости от выбранного шрифта, пространство, необходимое для каждого символа, не является постоянным. И поэтому мы не можем предположить, что 200 символов лучше всего уместятся в доступных пикселях. Пока (до 2 марта 2011 г.) во всех приведенных ниже ответах отсутствует этот момент, и, следовательно, ни один из них не обеспечивает надежного решения. - :(

LionHeart 02.03.2011 12:02

Нет, не совсем. Вы можете установить шрифт надежным способом, а затем измерить худший сценарий, например, сколько самых широких символов поместится. И если вам нужно быть на 100% уверенным, как браузер его обработал, это больше не проблема PHP.

Mołot 29.08.2013 15:59

Попробуйте эту ссылку, может вам помочь stackoverflow.com/a/26098951/3944217

edCoder 29.09.2014 15:38

Вы можете найти s($str)->truncateSafely(200) полезным, как указано в эта автономная библиотека.

caw 27.07.2016 03:02
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
191
4
182 571
29
Перейти к ответу Данный вопрос помечен как решенный

Ответы 29

Ответ принят как подходящий

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

substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n"));

Единственная вещь, которую не обрабатывает этот oneliner, - это случай, когда сам текст короче желаемой ширины. Чтобы справиться с этим крайним случаем, нужно сделать что-то вроде:

if (strlen($string) > $your_desired_width) 
{
    $string = wordwrap($string, $your_desired_width);
    $string = substr($string, 0, strpos($string, "\n"));
}

Вышеупомянутое решение имеет проблему преждевременного обрезания текста, если он содержит новую строку перед фактической точкой вырезания. Вот версия, которая решает эту проблему:

function tokenTruncate($string, $your_desired_width) {
  $parts = preg_split('/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE);
  $parts_count = count($parts);

  $length = 0;
  $last_part = 0;
  for (; $last_part < $parts_count; ++$last_part) {
    $length += strlen($parts[$last_part]);
    if ($length > $your_desired_width) { break; }
  }

  return implode(array_slice($parts, 0, $last_part));
}

Кроме того, вот тестовый класс PHPUnit, используемый для тестирования реализации:

class TokenTruncateTest extends PHPUnit_Framework_TestCase {
  public function testBasic() {
    $this->assertEquals("1 3 5 7 9 ",
      tokenTruncate("1 3 5 7 9 11 14", 10));
  }

  public function testEmptyString() {
    $this->assertEquals("",
      tokenTruncate("", 10));
  }

  public function testShortString() {
    $this->assertEquals("1 3",
      tokenTruncate("1 3", 10));
  }

  public function testStringTooLong() {
    $this->assertEquals("",
      tokenTruncate("toooooooooooolooooong", 10));
  }

  public function testContainingNewline() {
    $this->assertEquals("1 3\n5 7 9 ",
      tokenTruncate("1 3\n5 7 9 11 14", 10));
  }
}

РЕДАКТИРОВАТЬ :

Специальные символы UTF8, такие как «à», не обрабатываются. Добавьте 'u' в конце REGEX, чтобы обработать его:

$parts = preg_split('/([\s\n\r]+)/u', $string, null, PREG_SPLIT_DELIM_CAPTURE);

Похоже, что текст будет преждевременно обрезан, если перед желаемой шириной будет \n.

Kendall Hopkins 19.01.2012 04:09

@KendallHopkins: правда, проблема действительно есть. Я обновил ответ альтернативной реализацией, которая решает данную проблему.

Grey Panther 29.01.2012 13:26

Будет ли этот пример работать для строки, содержащей html-теги, такие как теги абзаца?

limitlessloop 04.07.2012 16:38

это действительно помогло мне, моя головная боль была из-за длинных букв Arabic и теперь она уменьшена до правильных слов с помощью функции tokenTruncate .. спасибо миллион :)

Aditya P Bhatt 07.07.2013 20:57

Почему бы не добавить: if (strlen ($ string) <= $ your_desired_width) return $ string; как первое заявление?

Darko Romanov 20.01.2015 11:26

Для однострочника tokenTruncate() используйте символ ascii unit seperator, для чего он предназначен: substr($content, 0, strpos(wordwrap($content, 350, chr(31)), chr(31)))

MacroMan 07.09.2015 13:44

Код на самом деле неверен и вернет длину, превышающую желаемую.

Case 11.11.2015 22:38

Любить это! Я добавил обрезку () вокруг окончательного возвращаемого значения. В противном случае вы получите конечный пробел.

Phil LaNasa 08.06.2016 03:50

Будьте осторожны, используйте mb_substr вместо substr при использовании UTF-8.

mandelf 13.04.2020 15:18

Используйте strpos и substr:

<?php

$longString = "I have a code snippet written in PHP that pulls a block of text.";
$truncated = substr($longString,0,strpos($longString,' ',30));

echo $truncated;

Это даст вам строку, усеченную до первого пробела после 30 символов.

Привет, если длина строки без пробела будет меньше 30, будет возвращена ошибка. и здесь результат будет из первых 31 символа, а не из 30 ..

Er. Anurag Jain 03.11.2012 09:05

Ну вот:

function neat_trim($str, $n, $delim='…') {
   $len = strlen($str);
   if ($len > $n) {
       preg_match('/(.{' . $n . '}.*?)\b/', $str, $matches);
       return rtrim($matches[1]) . $delim;
   }
   else {
       return $str;
   }
}

Спасибо, я нашел вашу функцию самой полезной и надежной из всех этих ответов для моих нужд. Однако как я могу заставить его поддерживать многобайтовые строки?

ctrlbrk 08.04.2020 05:48

Вроде поддерживает многобайтовую

Timo Huovinen 22.10.2020 00:29

Я бы использовал для этого функцию preg_match, так как вы хотите получить довольно простое выражение.

$matches = array();
$result = preg_match("/^(.{1,199})[\s]/i", $text, $matches);

Выражение означает «сопоставить любую подстроку, начинающуюся с начала длины 1-200 и заканчивающуюся пробелом». Результат - в $ result, а совпадение - в $ match. Это позаботится о вашем исходном вопросе, который конкретно заканчивается на любом месте. Если вы хотите, чтобы он заканчивался переводом строки, измените регулярное выражение на:

$result = preg_match("/^(.{1,199})[\n]/i", $text, $matches);

Это вернет первые 200 символов слов:

preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, 201));

Почти. Кажется, что он убирает последнее слово предложения, несмотря ни на что.

ReX357 04.08.2011 23:19

отлично работает, но я обнаружил ту же ошибку, что и ReX357. Когда есть более 1 слова, оно удаляет последнее.

Andres SK 26.11.2011 20:09

Просто заверните его в чек, чтобы убедиться, что строка длиннее, чем вы тестируете (как принятый ответ) if (strlen($string) > $your_desired_width) { preg_replace(...); }

Blair McMillan 18.04.2012 09:49

Я отредактировал ответ, включив совет @BlairMcMillan

Kim Stacks 26.03.2014 10:46

ВСЕГДА УДАЛЯЕТ ПОСЛЕДНЕЕ СЛОВО: P

TomeeNS 30.08.2015 16:06

Небольшое улучшение регулярного выражения: круглые скобки делают последний \ S + необязательным для соответствия, но они также захватывают эти символы. Поскольку нам не нужно захватывать эти символы, сделайте круглые скобки не захватывающими, например: /\s+?(?:\S+)?$/

pcronin 18.11.2015 18:28

@fubar не вижу, как это помогает. Разве результат substr () не должен быть таким же, учитывая, что строка обрезается до определенной длины?

John Law 01.10.2018 11:27

@JohnLaw, да, я понятия не имею, о чем я думал, когда опубликовал этот комментарий.

fubar 02.10.2018 00:51

Имейте в виду, что когда вы разбиваете слова по слову, некоторые языки, такие как китайский и японский, не используют пробел для разделения слов. Кроме того, злоумышленник может просто ввести текст без пробелов или использовать какой-либо Unicode, похожий на стандартный символ пробела, и в этом случае любое используемое вами решение может в конечном итоге отобразить весь текст в любом случае. Способом обойти это может быть проверка длины строки после разделения ее на пробелы как обычно, а затем, если строка все еще превышает ненормальный предел - может быть, в этом случае 225 символов - продолжая и тупо разбивая ее на этом пределе.

Еще одно предостережение относительно таких вещей, когда речь идет о символах, отличных от ASCII; строки, содержащие их, могут интерпретироваться стандартной функцией PHP strlen () как более длинные, чем они есть на самом деле, потому что один символ может занимать два или более байта вместо одного. Если вы просто используете функции strlen () / substr () для разделения строк, вы можете разделить строку посередине символа! Если есть сомнения, mb_strlen () / mb_substr () немного более надежны.

Вот моя функция, основанная на подходе @Cd-MaN.

function shorten($string, $width) {
  if (strlen($string) > $width) {
    $string = wordwrap($string, $width);
    $string = substr($string, 0, strpos($string, "\n"));
  }

  return $string;
}

На основе регулярного выражения @Justin Poliey:

// Trim very long text to 120 characters. Add an ellipsis if the text is trimmed.
if (strlen($very_long_text) > 120) {
  $matches = array();
  preg_match("/^(.{1,120})[\s]/i", $very_long_text, $matches);
  $trimmed_text = $matches[0]. '...';
}

$WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' '));

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

Я пробовал другие примеры, приведенные выше, и они не дали желаемых результатов.

Если заданная длина строки меньше максимальной длины, это отрежет все до последнего пробела. Чтобы этого избежать, заключите это в оператор if: if (strlen($str) > 200) { ... }

Amal Murali 08.05.2014 19:36

Просто и, вероятно, намного быстрее, чем другие решения.

Vladan 04.05.2015 16:06

Одна из проблем заключается в том, что он возвращает пустую строку, если строка не содержит пробела.

orrd 02.09.2015 00:00

Может быть упрощено до: $WidgetText = substr($string, 0, strpos($string, ' ', 200));

wranvaud 25.04.2019 11:15

Хорошо, поэтому я получил другую версию этого, основанную на приведенных выше ответах, но с учетом большего количества вещей (utf-8, \ n и & nbsp;), а также строку, удаляющую короткие коды wordpress, прокомментированные, если они используются с wp.

function neatest_trim($content, $chars) 
  if (strlen($content) > $chars) 
  {
    $content = str_replace('&nbsp;', ' ', $content);
    $content = str_replace("\n", '', $content);
    // use with wordpress    
    //$content = strip_tags(strip_shortcodes(trim($content)));
    $content = strip_tags(trim($content));
    $content = preg_replace('/\s+?(\S+)?$/', '', mb_substr($content, 0, $chars));

    $content = trim($content) . '...';
    return $content;
  }

Это небольшое исправление для ответа mattmac:

preg_replace('/\s+?(\S+)?$/', '', substr($string . ' ', 0, 201));

Единственное отличие состоит в том, чтобы добавить пробел в конец строки $. Это гарантирует, что последнее слово не обрезается в соответствии с комментарием ReX357.

У меня недостаточно очков репутации, чтобы добавить это в качестве комментария.

/*
Cut the string without breaking any words, UTF-8 aware 
* param string $str The text string to split
* param integer $start The start position, defaults to 0
* param integer $words The number of words to extract, defaults to 15
*/
function wordCutString($str, $start = 0, $words = 15 ) {
    $arr = preg_split("/[\s]+/",  $str, $words+1);
    $arr = array_slice($arr, $start, $words);
    return join(' ', $arr);
}

Использование:

$input = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna liqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.';
echo wordCutString($input, 0, 10); 

Это выведет первые 10 слов.

Функция preg_split используется для разделения строки на подстроки. Границы, по которым строка должна быть разделена, указываются с использованием шаблона регулярных выражений.

Функция preg_split принимает 4 параметра, но сейчас для нас актуальны только первые 3.

Первый параметр - паттерн Первый параметр - это шаблон регулярных выражений, по которому должна быть разбита строка. В нашем случае мы хотим разбить строку по границам слова. Поэтому мы используем предопределенный класс символов \s, который соответствует символам пробела, таким как пробел, табуляция, возврат каретки и перевод строки.

Второй параметр - входная строка Второй параметр - длинная текстовая строка, которую мы хотим разбить.

Третий параметр - предел Третий параметр указывает количество возвращаемых подстрок. Если вы установите ограничение на n, preg_split вернет массив из n элементов. Первые элементы n-1 будут содержать подстроки. Последний элемент (n th) будет содержать оставшуюся часть строки.

Я знаю, что это старое, но ...

function _truncate($str, $limit) {
    if (strlen($str) < $limit)
        return $str;
    $uid = uniqid();
    return array_shift(explode($uid, wordwrap($str, $limit, $uid)));
}

Следующее решение родилось, когда я заметил параметр $ break функции перенос слова:

string wordwrap ( string $str [, int $width = 75 [, string $break = "\n" [, bool $cut = false ]]] )

Вот решение:

/**
 * Truncates the given string at the specified length.
 *
 * @param string $str The input string.
 * @param int $width The number of chars at which the string will be truncated.
 * @return string
 */
function truncate($str, $width) {
    return strtok(wordwrap($str, $width, "...\n"), "\n");
}

Пример №1.

print truncate("This is very long string with many chars.", 25);

Приведенный выше пример выведет:

This is very long string...

Пример №2.

print truncate("This is short string.", 25);

Приведенный выше пример выведет:

This is short string.

это не работает, если в строке уже есть новый строковый символ (например, если вы пытаетесь извлечь description из сообщения в блоге)

supersan 08.06.2015 14:38

@supersan Всегда может выполнить предварительную обработку с помощью preg_replace('/\s+/', ' ', $description), чтобы заменить все пробельные символы одним пробелом;)

Mavelo 11.05.2018 20:40

Я использовал это раньше

<?php
    $your_desired_width = 200;
    $string = $var->content;
    if (strlen($string) > $your_desired_width) {
        $string = wordwrap($string, $your_desired_width);
        $string = substr($string, 0, strpos($string, "\n")) . " More...";
    }
    echo $string;
?>

Может быть, это кому-то поможет:

<?php

    $string = "Your line of text";
    $spl = preg_match("/([, \.\d\-''\"\"_()]*\w+[, \.\d\-''\"\"_()]*){50}/", $string, $matches);
    if (isset($matches[0])) {
        $matches[0] .= "...";
        echo "<br />" . $matches[0];
    } else {
        echo "<br />" . $string;
    }

?>

У меня есть функция, которая делает почти то, что вы хотите, если вы сделаете несколько правок, она точно подойдет:

<?php
function stripByWords($string,$length,$delimiter = '<br>') {
    $words_array = explode(" ",$string);
    $strlen = 0;
    $return = '';
    foreach($words_array as $word) {
        $strlen += mb_strlen($word,'utf8');
        $return .= $word." ";
        if ($strlen >= $length) {
            $strlen = 0;
            $return .= $delimiter;
        }
    }
    return $return;
}
?>

$shorttext = preg_replace('/^([\s\S]{1,200})[\s]+?[\s\S]+/', '', $fulltext);

Описание:

  • ^ - начать с начала строки
  • ([\s\S]{1,200}) - получить от 1 до 200 любого персонажа
  • [\s]+? - не включать пробелы в конце короткого текста, поэтому мы можем избежать word ... вместо word...
  • [\s\S]+ - соответствует всему остальному контенту

Тесты:

  1. regex101.com добавим к or еще несколько r
  2. regex101.comorrrr ровно 200 символов.
  3. regex101.com после пятого rorrrrr исключен.

Наслаждаться.

я не понимаю документацию PHP. Я знаю, что - это «замена», но в этом конкретном контексте, о чем он? пустая переменная?

oldboy 13.04.2018 23:15

@Anthony ссылка для соответствия внутри скобок ([\s\S]{1,200}). будет ссылаться на две вторые пары скобок, если они есть в шаблоне.

hlcs 14.04.2018 12:47

Вот как я это сделал:

$string = "I appreciate your service & idea to provide the branded toys at a fair rent price. This is really a wonderful to watch the kid not just playing with variety of toys but learning faster compare to the other kids who are not using the BooksandBeyond service. We wish you all the best";

print_r(substr($string, 0, strpos(wordwrap($string, 250), "\n")));

Я создаю функцию, более похожую на substr, и использую идею @Dave.

function substr_full_word($str, $start, $end){
    $pos_ini = ($start == 0) ? $start : stripos(substr($str, $start, $end), ' ') + $start;
    if (strlen($str) > $end){ $pos_end = strrpos(substr($str, 0, ($end + 1)), ' '); } // IF STRING SIZE IS LESSER THAN END
    if (empty($pos_end)){ $pos_end = $end; } // FALLBACK
    return substr($str, $pos_ini, $pos_end);
}

Ps .: Длина отреза может быть меньше подстр.

Здесь вы можете попробовать это

substr( $str, 0, strpos($str, ' ', 200) ); 

Это решение уже упоминалось в других ответах. Проблема в том, что он не работает, если длина строки меньше 200 символов или если она не содержит пробелов. Он также не ограничивает строку 200 символами, вместо этого он разбивает строку на пробел после 200 символов, что обычно не то, что вам нужно.

orrd 01.09.2015 23:04

Удивительно, насколько сложно найти идеальное решение этой проблемы. Я еще не нашел на этой странице ответа, который не дает сбоев, по крайней мере, в некоторых ситуациях (особенно, если строка содержит символы новой строки или табуляции, или если разрыв слова является чем-то другим, кроме пробела, или если строка имеет UTF- 8 многобайтовых символов).

Вот простое решение, которое работает во всех случаях. Здесь были похожие ответы, но модификатор «s» важен, если вы хотите, чтобы он работал с многострочным вводом, а модификатор «u» позволяет правильно оценивать многобайтовые символы UTF-8.

function wholeWordTruncate($s, $characterCount) 
{
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
    return $s;
}

Один из возможных крайних случаев с этим ... если строка вообще не имеет пробелов в первых символах $ characterCount, она вернет всю строку. Если вы предпочитаете, чтобы он заставлял разрыв в $ characterCount, даже если это не граница слова, вы можете использовать это:

function wholeWordTruncate($s, $characterCount) 
{
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) return $match[0];
    return mb_substr($return, 0, $characterCount);
}

Последний вариант, если вы хотите, чтобы он добавлял многоточие, если он усекает строку ...

function wholeWordTruncate($s, $characterCount, $addEllipsis = ' …') 
{
    $return = $s;
    if (preg_match("/^.{1,$characterCount}\b/su", $s, $match)) 
        $return = $match[0];
    else
        $return = mb_substr($return, 0, $characterCount);
    if (strlen($s) > strlen($return)) $return .= $addEllipsis;
    return $return;
}

Я полностью согласен с вами, ваш, кажется, один из редких примеров, который работает повсеместно со всеми языками Unicode. Отличная работа!

Timo Huovinen 22.10.2020 00:38

Я привел пример, основанный на вашем ответе здесь: github.com/thlib/php-truncate-words Это стало одним лайнером, вы могли бы быстро найти ошибки?

Timo Huovinen 22.10.2020 10:56

Добавлены операторы IF / ELSEIF в код из Дэйв и АмальМурали для обработки строк без пробелов

if ((strpos($string, ' ') !== false) && (strlen($string) > 200)) { 
    $WidgetText = substr($string, 0, strrpos(substr($string, 0, 200), ' ')); 
} 
elseif (strlen($string) > 200) {
    $WidgetText = substr($string, 0, 200);
}

Я считаю, что это самый простой способ сделать это:

$lines = explode('♦♣♠',wordwrap($string, $length, '♦♣♠'));
$newstring = $lines[0] . ' &bull; &bull; &bull;';

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

Я считаю, что это работает:

функция abbreviate_string_to_whole_word ($ строка, $ max_length, $ buffer) {

if (strlen($string)>$max_length) {
    $string_cropped=substr($string,0,$max_length-$buffer);
    $last_space=strrpos($string_cropped, " ");
    if ($last_space>0) {
        $string_cropped=substr($string_cropped,0,$last_space);
    }
    $abbreviated_string=$string_cropped."&nbsp;...";
}
else {
    $abbreviated_string=$string;
}

return $abbreviated_string;

}

Буфер позволяет вам регулировать длину возвращаемой строки.

Использовать это:

следующий код удалит ','. Если у вас есть другой символ или подстрока, вы можете использовать его вместо ','

substr($string, 0, strrpos(substr($string, 0, $comparingLength), ','))

// если у вас есть другая строковая учетная запись для

substr($string, 0, strrpos(substr($string, 0, $comparingLength-strlen($currentString)), ','))

Хотя это довольно старый вопрос, я решил, что предоставлю альтернативу, поскольку он не упоминался и действителен для PHP 4.3+.

Вы можете использовать семейство функций sprintf для усечения текста с помощью модификатора точности %.ℕs.

A period . followed by an integer who's meaning depends on the specifier:

  • For e, E, f and F specifiers: this is the number of digits to be printed after the decimal point (by default, this is 6).
  • For g and G specifiers: this is the maximum number of significant digits to be printed.
  • For s specifier: it acts as a cutoff point, setting a maximum character limit to the string

Простое усечение https://3v4l.org/QJDJU

$string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var_dump(sprintf('%.10s', $string));

Результат

string(10) "0123456789"

Расширенное усечение https://3v4l.org/FCD21

Поскольку sprintf работает аналогично substr и частично обрезает слова. Приведенный ниже подход гарантирует, что слова не будут обрезаны с помощью strpos(wordwrap(..., '[break]'), '[break]') со специальным разделителем. Это позволяет нам получить позицию и убедиться, что мы не совпадаем со стандартными структурами предложений.

Возврат строки без частичного обрезания слов и не превышающей заданную ширину, при желании с сохранением разрывов строк.

function truncate($string, $width, $on = '[break]') {
    if (strlen($string) > $width && false !== ($p = strpos(wordwrap($string, $width, $on), $on))) {
        $string = sprintf('%.'. $p . 's', $string);
    }
    return $string;
}
var_dump(truncate('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', 20));

var_dump(truncate("Lorem Ipsum is simply dummy text of the printing and typesetting industry.", 20));

var_dump(truncate("Lorem Ipsum\nis simply dummy text of the printing and typesetting industry.", 20));

Результат

/* 
string(36) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"  
string(14) "Lorem Ipsum is" 
string(14) "Lorem Ipsum
is" 
*/

Результаты с использованием wordwrap($string, $width) или strtok(wordwrap($string, $width), "\n")

/*
string(14) "Lorem Ipsum is"
string(11) "Lorem Ipsum"
*/

// a looonnng string ...
$str = "Le Lorem Ipsum est simplement du 
faux texte employé dans la composition et 
la mise en page avant impression. 
Le Lorem Ipsum est le faux texte standard de 
l'imprimerie depuis les années 1500, quand un 
imprimeur anonyme assembla ensemble des morceaux 
de texte pour réaliser un livre spécimen de polices
de texte. Il n'a pas fait que survivre cinq siècles,
mais s'est aussi adapté à la bureautique informatique,
sans que son contenu n'en soit modifié. Il a été 
popularisé dans les années 1960 grâce à la vente 
de feuilles Letraset contenant des passages du
Lorem Ipsum, et, plus récemment, par son inclusion 
dans des applications de mise en page de texte, 
comme Aldus PageMaker";
// number chars to cut
$number_to_cut = 300;
// string truncated in one line !
$truncated_string = 
substr($str, 0, strrpos(substr($str, 0, $number_to_cut), ' '));
// test return
echo $truncated_string;

// variation (add ellipsis) : echo $truncated_string.' ...';

// output :
/* Le Lorem Ipsum est simplement du 
faux texte employé dans la composition et 
la mise en page avant impression. 
Le Lorem Ipsum est le faux texte standard de 
l'imprimerie depuis les années 1500, quand un 
imprimeur anonyme assembla ensemble des morceaux 
de texte pour réaliser un livre
*/

Вы можете использовать это:

function word_shortener($text, $words=10, $sp='...'){

  $all = explode(' ', $text);
  $str = '';
  $count = 1;

  foreach($all as $key){
    $str .= $key . ($count >= $words ? '' : ' ');
    $count++;
    if ($count > $words){
      break;
    }
  }

  return $str . (count($all) <= $words ? '' : $sp);

}

Примеры:

word_shortener("Hello world, this is a text", 3); // Hello world, this...
word_shortener("Hello world, this is a text", 3, ''); // Hello world, this
word_shortener("Hello world, this is a text", 3, '[read more]'); // Hello world, this[read more]

Другие вопросы по теме