Formatting Output

Getting numbers and text to line up — two decimal places for prices, padded columns for reports, zero-filled invoice numbers — is the job of printf and sprintf. This lesson covers their format specifiers, plus number_format and the options for displaying values in other languages and currencies.

printf and sprintf

printf prints a formatted string; sprintf returns it instead. The first argument is a template where each % placeholder is replaced by the next argument:

PHP
<?php

$name = "Kai";
$items = 3;
$total = 47.5;

printf("%s bought %d items for %.2f EUR\n", $name, $items, $total);

$line = sprintf("Invoice #%05d", 42);
echo $line, "\n";
Output
Kai bought 3 items for 47.50 EUR
Invoice #00042

Conversion specifiers

SpecifierFormats asExampleResult
%sStringsprintf('%s', 'hi')hi
%dIntegersprintf('%d', 42.9)42
%fFloat (6 decimals by default)sprintf('%.2f', 3.14159)3.14
%eScientific notationsprintf('%.1e', 1500)1.5e+3
%x / %XHexadecimalsprintf('%X', 255)FF
%b / %oBinary / octalsprintf('%b', 5)101
%cCharacter from a codesprintf('%c', 65)A
%%A literal percent signsprintf('%d%%', 50)50%

Width, padding and alignment

Between the % and the letter you can add a width, a padding character, alignment and precision. A number sets the minimum width (right-aligned); - left-aligns; 0 or 'x sets the padding character; + always shows the sign:

PHP
<?php

printf("[%8s]\n", "right");
printf("[%-8s]\n", "left");
printf("[%08.2f]\n", 3.14159);
printf("[%'*10s]\n", "stars");
printf("[%+d] [%+d]\n", 5, -5);
printf("[%.3s]\n", "truncated");      // precision on strings cuts them
Output
[   right]
[left    ]
[00003.14]
[*****stars]
[+5] [-5]
[tru]

A formatted report

PHP
<?php

$rows = [
    ["Keyboard", 1, 49.99],
    ["Mouse", 2, 19.50],
    ["USB cable", 10, 3.25],
];

printf("%-12s%5s%10s\n", "Item", "Qty", "Total");
echo str_repeat("-", 27), "\n";

$sum = 0;
foreach ($rows as [$item, $qty, $price]) {
    printf("%-12s%5d%10.2f\n", $item, $qty, $qty * $price);
    $sum += $qty * $price;
}
printf("%-17s%10.2f\n", "Grand total", $sum);
Output
Item          Qty     Total
---------------------------
Keyboard        1     49.99
Mouse           2     39.00
USB cable      10     32.50
Grand total          121.49

(foreach ($rows as [$item, $qty, $price]) unpacks each row — lesson 26.)

Numbered placeholders

%1$s refers to the first argument, %2$s to the second, and so on. That lets you reuse an argument or change the order — useful in translated text, where word order differs between languages:

PHP
<?php

printf("%1\$s scored %2\$d points. Well done, %1\$s!\n", "Lena", 87);
printf("%2\$s %1\$s\n", "world", "Hello");
Output
Lena scored 87 points. Well done, Lena!
Hello world

Inside double quotes, the $ must be escaped as \$ — or use single quotes for the template.

vsprintf and friends

When the values are already in an array, vsprintf takes the array instead of separate arguments. fprintf writes to a file or stream:

PHP
<?php

$parts = [2026, 3, 9];
echo vsprintf("%04d-%02d-%02d", $parts), "\n";

fprintf(STDOUT, "%s has %d characters\n", "PHP", 3);
Output
2026-03-09
PHP has 3 characters

number_format

For displaying numbers with thousands separators, number_format is simpler than printf:

PHP
<?php

echo number_format(1234567.891), "\n";
echo number_format(1234567.891, 2), "\n";
echo number_format(1234567.891, 2, ',', '.'), "\n";
echo number_format(1234567.891, 2, '.', ' '), "\n";
Output
1,234,568
1,234,567.89
1.234.567,89
1 234 567.89

Formatting for other languages

printf always uses a dot as the decimal separator (unlike C, it ignores the locale for %f; %F is the same). For locale-aware currency and number formatting — "1.234,56 €" in Germany, "€1,234.56" in Ireland — the intl extension provides NumberFormatter:

PHP
<?php

$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234.56, 'EUR'), "\n";    // 1.234,56 €

$fmt = new NumberFormatter('en_IN', NumberFormatter::DECIMAL);
echo $fmt->format(12345678), "\n";                  // 1,23,45,678

intl is a separate extension, usually installed as php-intl. (It isn't run here because the PHP build used for this course doesn't include it.)

Try it yourself

Print a receipt with aligned columns. Then try changing the widths and the padding character.

Try it yourself · main.php
Edit the code, copy it into main.php, then run it with php main.php (PHP 8.5). How to install PHP
Output
Sandwich      6.50
Juice         2.75
Cookie        1.80
==================
Subtotal     11.05
Tax 8%        0.88
Total        11.93