Str::wordCount
Counts the words in a string, optionally treating extra characters as part of a word.
Str::wordCount(string $string, ?string $characters = null): int- Added in Laravel 8.38
Parameters
| Parameter | Type | Description |
|---|---|---|
$$string | string | The string to count words in. |
$$charactersoptional | string|null= null | Additional characters to treat as part of a word, given as a plain string of characters. Ranges may be written as 'a..z'. |
Return value
intThe number of words found, where a word is a run of letters plus any additional characters supplied.
Changelog
- PHP 9.xThe $characters argument was added, allowing digits and other symbols to be counted as word characters.
Str::wordCount is a direct pass-through to PHP's str_word_count. A word is a run of alphabetic characters; the apostrophe and the hyphen are already included, so don't and well-known each count as one.
Use it for reading-time estimates, word-limit checks on user submissions, and rough content metrics.
The big caveat
It is not multibyte aware. str_word_count works on bytes against the C locale, so any non-ASCII letter acts as a word separator. naïve approach counts as 3, not 2, because naïve is split into na and ve. On French, German, Turkish or any non-Latin text the number is simply wrong. For accurate counts on international content, use preg_split('/\s+/u', ...) on a squished string instead.
Other things to know
- Digits are not letters, so
PHP 8 rockscounts as 2. Pass'0123456789'as the second argument to count numeric tokens. - Punctuation and repeated whitespace are ignored, so pre-squishing changes nothing about the count.
- An empty string returns
0, and a string of only punctuation does too.
Example
When to use it
- Estimate a reading time for an article by dividing the count by a words-per-minute figure.
- Enforce a word limit on a submitted bio or abstract that a character limit cannot express.
- Report rough content length in an editorial dashboard.
Frequently asked questions
Why does Str::wordCount return the wrong number for accented text?
Because it wraps str_word_count, which is byte based and treats any non-ASCII byte as a separator, so 'naïve' counts as two words. Split on whitespace with preg_split('/\\s+/u', ...) for international text.
Does Str::wordCount count numbers as words?
Not by default — digits are not alphabetic. Pass the digits as the second argument, as in Str::wordCount('PHP 8 rocks', '0123456789'), to include numeric tokens in the total.
How do I estimate reading time in Laravel?
Divide Str::wordCount by a words-per-minute figure, typically 200, and round up with a minimum of one minute. Squish the text first so that stray whitespace does not affect anything else you derive from it.
More examples
A reading-time estimate
Prints "10 words, 1 min read". The max(1, ...) guard matters because any article under 200 words would otherwise report zero minutes. The two dumps are 2 and 4: without the digit list only "Vol" and "of" are words, and adding the digits brings "3" and "5" into the count.
<?php
use Illuminate\Support\Str;
$text = 'Laravel is a web application framework with expressive, elegant syntax.';
$words = Str::wordCount(Str::squish($text));
$minutes = max(1, (int) ceil($words / 200));
echo $words, ' words, ', $minutes, ' min read', PHP_EOL;
// Counting a version string with and without digits.
var_dump(Str::wordCount('Vol. 3 of 5'));
var_dump(Str::wordCount('Vol. 3 of 5', '0123456789'));A multibyte-safe alternative
Str::wordCount reports 10 for a seven-word French sentence, because é, ï and à each split their word. The squish-and-split helper reports 7. Use the helper whenever the content is not guaranteed to be plain ASCII; it is also cheap enough to register as a Str macro.
<?php
use Illuminate\Support\Str;
function unicodeWordCount(string $value): int
{
$value = Str::squish($value);
return $value === '' ? 0 : count(preg_split('/\s+/u', $value));
}
$french = "Une idée naïve à propos du café";
var_dump(Str::wordCount($french));
var_dump(unicodeWordCount($french));
Discussion