Strings7 min readExamples run on PHP 8.5.10

ucwords()

Learn how PHP 8.4 ucwords() capitalizes word starts, how custom separators work, and where ASCII-only behavior and mixed casing catch people out.

Signature

ucwords(string $string, string $separators = " \t\r\n\f\v"): string

Purpose

ucwords() turns the first character of every word in a string into an uppercase letter and returns the result. It is a quick way to prepare display text such as headings, labels or names from lowercase input. It does not touch the rest of each word, so it is a simple, predictable tool rather than a full title-case engine.

Signature

Parameters and defaults

  • $string is the text to convert.
  • $separators lists the characters that mark the boundary between words. A word is simply a run of characters that are not in this list. The default contains a space, horizontal tab, carriage return, newline, form feed and vertical tab.

The separator list is a set of individual characters, not a delimiter string. Passing " -'" means that space, hyphen and apostrophe are each separators.

Return value and failure cases

The function returns a new string; the original is not modified. It does not return false and does not signal an error for unusual text. An empty string comes back as an empty string. Passing a value that is not a string follows the normal PHP type rules, so a file using declare(strict_types=1) will raise a TypeError for an array or integer argument.

Only ASCII letters from a to z are converted. Since PHP 8.2.0 the result no longer depends on the locale set with setlocale(). The manual also notes that the function is binary-safe.

Example 1: basic use and mixed case

The function uppercases word starts but never lowercases anything. If your input is already in capitals, it will stay that way unless you lowercase it first.

Example
<?php
$title = 'hello world from php';
echo ucwords($title), PHP_EOL;
$shout = 'HELLO WORLD';
echo ucwords($shout), PHP_EOL;
echo ucwords(strtolower($shout)), PHP_EOL;
Output
Hello World From Php
HELLO WORLD
Hello World

The first line capitalizes each word. The second is unchanged because the letters are already uppercase. The third normalizes with strtolower() first, which is the usual pattern for cleaning shouted text.

Example 2: custom separators

By default only whitespace starts a new word. A hyphen or apostrophe does not, so names with those characters need an explicit separator list.

Example
<?php
$name = "mary-jane o'neil";
echo ucwords($name), PHP_EOL;
echo ucwords($name, " -'"), PHP_EOL;
echo ucwords('hello|world!', '|'), PHP_EOL;
Output
Mary-jane O'neil
Mary-Jane O'Neil
Hello|World!

With the default list, jane and neil stay lowercase. Adding - and ' fixes that. In the last call only the pipe separates words, so world! is capitalized after it, and the exclamation mark is just part of the word.

Example 3: edge cases

The next example uses json_encode() so that whitespace and bytes are visible in the output.

Example
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(ucwords("  tabs\tand\nlines"), $flags), PHP_EOL;
echo json_encode(ucwords('élan vital 3d'), $flags), PHP_EOL;
echo json_encode(ucwords('a-b c', ''), $flags), PHP_EOL;
Output
"  Tabs\tAnd\nLines"
"élan Vital 3d"
"A-b c"

Leading whitespace is preserved and the first real word is still capitalized. Tabs and newlines act as separators. The accented é is not an ASCII letter, so it is left alone, while vital is capitalized. The text 3d starts with a digit, which has no uppercase form, so it is unchanged. With an empty separator list nothing splits the text into words, so only the very first character is capitalized.

Edge cases to remember

  • Multibyte text: a UTF-8 letter such as é or ß is not converted. For multibyte-aware title casing, the manual points to mb_convert_case() with MB_CASE_TITLE.
  • A word that begins with a non-letter, such as a quote, digit or bracket, is not capitalized, because the first character is what gets checked. For example "(draft) notes" stays (draft) Notes.
  • Repeated separators are harmless; each one simply passes through unchanged.
  • Small words like of and the are capitalized as well. The function has no exception list.

Common mistakes

  1. Expecting the rest of each word to become lowercase. Use strtolower() first when the source may contain capitals.
  2. Forgetting that a custom $separators value replaces the default list. If you pass "-" only, spaces no longer separate words. Include a space explicitly when you need both.
  3. Treating the separator argument as a multi-character delimiter. It is a set of single-byte characters.
  4. Using it on non-English names and expecting accented letters to change. It is ASCII-only by design.
  5. Assuming it handles names like McDonald or van der Berg. It capitalizes by position only and cannot know such rules.
  • ucfirst() capitalizes only the first character of the whole string.
  • strtoupper() and strtolower() change the case of the entire string.
  • mb_convert_case() handles multibyte text, including title-case mode.

Recap

ucwords() capitalizes the first ASCII letter of each word and leaves everything else as is. Words are delimited by whitespace by default, and you can supply your own separator characters. Combine it with strtolower() for clean results, and reach for the multibyte functions when working with non-ASCII text.

Tested examples

Basic use and mixed case
<?php
$title = 'hello world from php';
echo ucwords($title), PHP_EOL;
$shout = 'HELLO WORLD';
echo ucwords($shout), PHP_EOL;
echo ucwords(strtolower($shout)), PHP_EOL;
Output
Hello World From Php
HELLO WORLD
Hello World
Custom separators
<?php
$name = "mary-jane o'neil";
echo ucwords($name), PHP_EOL;
echo ucwords($name, " -'"), PHP_EOL;
echo ucwords('hello|world!', '|'), PHP_EOL;
Output
Mary-jane O'neil
Mary-Jane O'Neil
Hello|World!
Edge cases
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(ucwords("  tabs\tand\nlines"), $flags), PHP_EOL;
echo json_encode(ucwords('élan vital 3d'), $flags), PHP_EOL;
echo json_encode(ucwords('a-b c', ''), $flags), PHP_EOL;
Output
"  Tabs\tAnd\nLines"
"élan Vital 3d"
"A-b c"