Str::words
Truncates a string to a maximum number of words and appends an ending.
Str::words(string $value, int $words = 100, string $end = '...'): string- Added in Laravel 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$value | string | The string to truncate. Words are runs of non-whitespace characters. |
$$wordsoptional | int= 100 | Maximum number of words to keep. Must be a positive integer; the value is interpolated into a regular expression quantifier. |
$$endoptional | string= '...' | Appended only when truncation actually happened. |
Return value
stringThe first $words words followed by $end, or the original string when it already has that many words or fewer.
Changelog
- PHP 9.xThe word-matching pattern gained the u modifier, so multibyte text is no longer cut mid-character.
Str::words keeps the first N whitespace-separated tokens and appends an ending. It differs from Str::limit, which counts characters: words() never cuts a word in half, but the output length varies with the content, so it can overflow a fixed-height card.
Reach for it for excerpts, list previews, notification summaries and search results — anywhere a partial word would look broken.
What trips people up
- The ending is only appended when truncation happened. A short string comes back untouched with no ellipsis, which is correct but means the presence of
...is not a reliable signal. - Leading whitespace is preserved. The regex matches from the start of the string including its leading spaces, so
' leading spaces here now'limited to two words returns' leading spaces...'with the indentation intact. CallStr::squishfirst. - It is not HTML aware. Tags count toward the word total and a truncation can land inside a tag, leaving unbalanced markup. Strip tags first, or use a purpose-built HTML truncator.
- Trailing punctuation on the last kept word stays, so you often get
expressive,.... - A limit of
0produces an invalid quantifier, emits a PCRE warning and returns the full string.
Example
When to use it
- Build a post excerpt for an index page where a half-word would look broken.
- Shorten a long comment into a notification summary of a fixed word count.
- Trim a search result snippet down to a readable preview length.
Frequently asked questions
What is the difference between Str::words and Str::limit?
Str::words counts whole words and never cuts one in half, while Str::limit counts characters and gives a predictable maximum length. Use words for readable excerpts and limit when the output must fit a fixed character budget.
Why does Str::words not add the ellipsis?
Because the string already had that many words or fewer, so no truncation occurred and the value is returned unchanged. The ending is only appended when something was actually cut off.
Is Str::words safe to use on HTML?
No. Tags are counted as words and a cut can land inside one, leaving unbalanced markup. Run strip_tags and Str::squish over the value first, then truncate the plain text.
More examples
words versus limit
words() returns "Laravel is a web application framework..." with the last word intact, while limit() returns "Laravel is a web application framework w..." and cuts "with" in half. Use words() when whole words matter and limit() when a hard character budget matters. The last two lines show that the ending is arbitrary and that Str::of()->words() takes the same arguments.
<?php
use Illuminate\Support\Str;
$body = 'Laravel is a web application framework with expressive, elegant syntax.';
var_dump(Str::words($body, 6));
var_dump(Str::limit($body, 40));
// A custom ending, and the fluent equivalent.
var_dump(Str::words($body, 6, ' [read more]'));
var_dump(Str::of($body)->words(4, '…')->value());A safe excerpt from HTML content
Prints "Laravel is a web application framework…". The three steps matter in this order: strip_tags removes markup so tags cannot be counted as words or split open, squish collapses the newline and double space that the markup left behind, and only then does words() truncate. Calling Str::words directly on the raw HTML would have produced "<p>Laravel is a…" with an unclosed paragraph tag.
<?php
use Illuminate\Support\Str;
function excerpt(string $html, int $words = 25): string
{
$text = Str::squish(strip_tags($html));
return Str::words($text, $words, '…');
}
$html = "<p>Laravel is a <strong>web application</strong> framework\n"
. "with expressive, elegant syntax.</p>";
echo excerpt($html, 6), PHP_EOL;
Discussion