Strings7 min readExamples run on PHP 8.5.10

sprintf()

Learn how PHP 8.4 sprintf() builds formatted strings with padding, precision, argument numbering and type specifiers, plus its errors and common pitfalls.

Signature

sprintf(string $format, mixed ...$values): string

Purpose

sprintf() builds a string from a template and a list of values. It does not print anything; it returns the result, so you can store it, compare it, pass it to another function, or echo it yourself. Typical uses are zero-padded identifiers, aligned text columns, fixed-decimal prices and message templates that need their values in a different order.

Signature

Parameters

$format is the template. Ordinary characters are copied unchanged. Each conversion specification starts with % and follows this shape: %[argnum$][flags][width][.precision]specifier.

  • argnum: an integer followed by $, such as %2$s. It selects which argument to use, so values can be reordered or reused. It must come immediately after the %.
  • flags: - left-justifies, + shows a sign on positive numbers, 0 pads with zeros, a space pads with spaces (the default), and 'x pads with the character x.
  • width: the minimum length of the converted value. A * takes the width from an extra integer argument.
  • precision: a . followed by a number. For e, E, f and F it is the number of digits after the decimal point (default 6). For s it is the maximum number of characters. For g, G, h and H it is the maximum number of significant digits.
  • specifier: the conversion. Common ones are d (signed integer), u (unsigned), s (string), f/F (float), e/E (scientific), x/X (hex), o (octal), b (binary), c (character from a code) and % (a literal percent sign, which consumes no argument).

...$values holds the values to insert, consumed in order unless argnum says otherwise. Values are coerced to the type the specifier needs.

Return value and failures

The function returns the formatted string. Since PHP 8.0 it no longer returns false on failure. Instead it throws:

  • ArgumentCountError when fewer arguments are supplied than the format requires;
  • ValueError when no arguments are given, or when a width or precision is negative or larger than PHP_INT_MAX.

Example 1: padding, signs and number bases

Example
<?php
echo sprintf("%04d-%02d-%02d", 2005, 5, 6), PHP_EOL;
echo sprintf("%'.9d", 123), PHP_EOL;
echo sprintf("%+d %+d", 5, -5), PHP_EOL;
echo sprintf("%5.1f%% %X %b", 45.67, 255, 5), PHP_EOL;
Output
2005-05-06
......123
+5 -5
 45.7% FF 101

The first line builds an ISO-style date from integers. The second pads with dots using the ' flag. The third forces a + on positive numbers. The last one rounds to one decimal, prints a literal %, then shows hexadecimal and binary.

Example 2: an aligned text table

Example
<?php
$rows = [['Pen', 1.5, 3], ['Notebook', 12.249, 2]];
foreach ($rows as [$name, $price, $qty]) {
    echo sprintf("%-10s|%8.2f|%3d", $name, $price, $qty), PHP_EOL;
}
Output
Pen       |    1.50|  3
Notebook  |   12.25|  2

The - flag left-aligns the name in a ten-character field, while the numbers stay right-aligned by default. %8.2f reserves eight characters and rounds to two decimals.

Example 3: argument numbering and errors

Example
<?php
echo sprintf('The %2$s contains %1$04d monkeys.', 5, 'tree'), PHP_EOL;
try {
    echo sprintf('%d and %d', 1), PHP_EOL;
} catch (ArgumentCountError $e) {
    echo get_class($e), PHP_EOL;
}
Output
The tree contains 0005 monkeys.
ArgumentCountError

With %2$s and %1$04d, the template decides the order, which helps when translated sentences place values differently. The second call asks for two values but receives one, so PHP throws ArgumentCountError.

Edge cases

  • Rounding is for display. %.2f formats a float but the stored value is unchanged. Floats such as 12.249 are binary approximations, so values that sit exactly on a rounding boundary can surprise you.
  • Locale. %f is locale aware, while %F is not. Use %F when the output must always use a dot as the decimal separator.
  • Width counts bytes. With multibyte text, %s, width and precision work on bytes, so padding or truncation can split or misalign UTF-8 characters.
  • %c ignores padding. It outputs a single character from an integer code regardless of width.
  • Precision on strings truncates. %.3s keeps at most three characters (bytes).
  • Bare period. The manual records a change in PHP 8.5.0 for a precision written as just a period. To stay portable, always write an explicit number such as %.0f.

Common mistakes

  1. Forgetting to echo. sprintf() returns the string; printf() is the function that outputs it.
  2. Mismatched order. Passing values in a different order than the placeholders swaps them silently, because %d and %s will happily coerce almost anything. Use argnum$ when order may vary.
  3. Unescaped percent signs. A literal percent must be written %%. A lone % followed by text is parsed as a conversion.
  4. Putting argnum$ after flags. %04$d is wrong; write %1$04d.
  5. Mixing user-controlled formats with data. Never let untrusted input become the format string, since it controls how many arguments are required.
  6. Using it for thousands separators. sprintf() has no grouping option; use number_format() for that.

printf() outputs a formatted string, vsprintf() takes the values as an array, fprintf() writes to a stream, number_format() groups thousands, sscanf() parses text using a similar format, and date() formats timestamps.

Recap

Use sprintf() when you want a returned, precisely formatted string. Learn the order %[argnum$][flags][width][.precision]specifier, prefer %F for locale-independent floats, escape literal percents as %%, and expect ArgumentCountError when arguments are missing.

Tested examples

Padding, signs and number bases
<?php
echo sprintf("%04d-%02d-%02d", 2005, 5, 6), PHP_EOL;
echo sprintf("%'.9d", 123), PHP_EOL;
echo sprintf("%+d %+d", 5, -5), PHP_EOL;
echo sprintf("%5.1f%% %X %b", 45.67, 255, 5), PHP_EOL;
Output
2005-05-06
......123
+5 -5
 45.7% FF 101
An aligned text table
<?php
$rows = [['Pen', 1.5, 3], ['Notebook', 12.249, 2]];
foreach ($rows as [$name, $price, $qty]) {
    echo sprintf("%-10s|%8.2f|%3d", $name, $price, $qty), PHP_EOL;
}
Output
Pen       |    1.50|  3
Notebook  |   12.25|  2
Argument numbering and errors
<?php
echo sprintf('The %2$s contains %1$04d monkeys.', 5, 'tree'), PHP_EOL;
try {
    echo sprintf('%d and %d', 1), PHP_EOL;
} catch (ArgumentCountError $e) {
    echo get_class($e), PHP_EOL;
}
Output
The tree contains 0005 monkeys.
ArgumentCountError