Strings7 min readExamples run on PHP 8.5.10

ucfirst()

Learn how PHP 8.4 ucfirst() uppercases the first ASCII letter of a string, what it leaves alone, and how to avoid common casing mistakes.

Signature

ucfirst(string $string): string

Purpose

ucfirst() capitalizes the first character of a string. It is a small helper for turning hello into Hello, building labels from identifiers, or producing method names such as getEmail from a field name. It only looks at the first byte of the string and never touches the rest, so it is cheap and predictable.

Signature

Parameters and defaults

  • $string: the input string. It is required and has no default value.

The function takes no options. It does not accept a locale, an encoding or a list of delimiters. If you need those, look at the related functions below.

Return value and failure cases

ucfirst() returns a new string. The original variable is not modified. The first character is converted only if it is an ASCII letter from a (0x61) to z (0x7a). In every other situation the string is returned unchanged.

There is no false return and no warning for odd input. An empty string simply gives back an empty string. The only failure you can run into is a type problem: passing an array, or an object that cannot be converted to a string, throws a TypeError. In strict-types mode, passing an integer or a float also throws, while in the default coercive mode scalars are converted to strings first. Convert values explicitly, and do not pass null, so your intent is clear.

Since PHP 8.2.0, the conversion no longer depends on the locale set with setlocale(). Only ASCII characters are converted, so the result is the same on every server.

Example 1: the basics

The first example shows that ucfirst() leaves the remaining letters alone. To get a conventional sentence-style result from shouting text, lowercase it first.

Example
<?php
echo json_encode([
    ucfirst('hello world'),
    ucfirst('HELLO'),
    ucfirst(strtolower('HELLO')),
    ucfirst(''),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";
Output
["Hello world","HELLO","Hello",""]

Example 2: characters that are not changed

If the first byte is a digit, a space, an underscore, a newline or a non-ASCII letter, nothing happens. This surprises people who expect the first visible letter to be capitalized.

Example
<?php
$values = ['123abc', ' apple', '_name', 'élan', "\nline"];
$result = [];
foreach ($values as $value) {
    $result[] = ucfirst($value);
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["123abc"," apple","_name","élan","\nline"]

The leading space in ' apple' blocks the conversion, and é is outside the ASCII range, so 'élan' is unchanged. The newline in the last value is shown as \n because JSON escapes it.

Example 3: building readable labels

Because ucfirst() works on one string, it combines well with array_map() when you split an identifier into words.

Example
<?php
function formatLabel(string $key): string
{
    $words = explode('_', strtolower($key));
    $words = array_map('ucfirst', $words);
    return implode(' ', $words);
}

echo formatLabel('FIRST_NAME'), "\n";
echo formatLabel('postal_code'), "\n";
Output
First Name
Postal Code

The input is lowercased first, so mixed-case keys still produce a consistent result.

Edge cases

  • Empty string: returns an empty string.
  • Leading whitespace: the string is unchanged if the first byte is a space, tab or newline. Use trim() first if that is not what you want.
  • Already uppercase: the string is unchanged, and the rest of the letters are never lowercased.
  • Multibyte text: accented letters, Greek, Cyrillic and similar scripts are not converted. A UTF-8 character spans several bytes, and ucfirst() only handles ASCII a to z. For such text, combine mb_substr() with mb_strtoupper(), or consider mb_convert_case(), keeping in mind that title-case mode affects every word.
  • Digits and symbols: they have no case, so they pass through untouched.

Common mistakes

  1. Expecting the rest of the string to change. ucfirst('PHP') is still PHP. Lowercase the string first when you need a normalized form.
  2. Using it for names in non-English text. Names that begin with a non-ASCII letter will not be capitalized.
  3. Expecting every word to be capitalized. ucfirst('hello big world') only changes the first word. Use ucwords() for each word.
  4. Ignoring the return value. The function does not modify its argument, so calling ucfirst($name); on its own does nothing useful. Assign the result.
  5. Relying on locale settings. Older code sometimes called setlocale() to affect case conversion. In PHP 8.2 and later, this has no effect on ucfirst().
  • lcfirst(): lowercases the first character.
  • strtolower(): lowercases the whole string.
  • strtoupper(): uppercases the whole string.
  • ucwords(): uppercases the first character of each word.
  • mb_convert_case(): performs case conversion for multibyte text.

Recap

ucfirst(string $string): string returns a copy of the string with its first character uppercased, but only when that character is an ASCII letter a to z. It leaves the rest of the string unchanged, ignores locale in PHP 8.2 and later, and gives back the input as is for empty strings, leading spaces, digits and non-ASCII letters. Pair it with strtolower() for normalized output and with ucwords() or the multibyte functions when the job is bigger than one ASCII letter.

Tested examples

Basic ucfirst() behavior
<?php
echo json_encode([
    ucfirst('hello world'),
    ucfirst('HELLO'),
    ucfirst(strtolower('HELLO')),
    ucfirst(''),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";
Output
["Hello world","HELLO","Hello",""]
Characters that are not changed
<?php
$values = ['123abc', ' apple', '_name', 'élan', "\nline"];
$result = [];
foreach ($values as $value) {
    $result[] = ucfirst($value);
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["123abc"," apple","_name","élan","\nline"]
Building readable labels
<?php
function formatLabel(string $key): string
{
    $words = explode('_', strtolower($key));
    $words = array_map('ucfirst', $words);
    return implode(' ', $words);
}

echo formatLabel('FIRST_NAME'), "\n";
echo formatLabel('postal_code'), "\n";
Output
First Name
Postal Code