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 $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";
Kai bought 3 items for 47.50 EUR Invoice #00042
Conversion specifiers
| Specifier | Formats as | Example | Result |
|---|---|---|---|
%s | String | sprintf('%s', 'hi') | hi |
%d | Integer | sprintf('%d', 42.9) | 42 |
%f | Float (6 decimals by default) | sprintf('%.2f', 3.14159) | 3.14 |
%e | Scientific notation | sprintf('%.1e', 1500) | 1.5e+3 |
%x / %X | Hexadecimal | sprintf('%X', 255) | FF |
%b / %o | Binary / octal | sprintf('%b', 5) | 101 |
%c | Character from a code | sprintf('%c', 65) | A |
%% | A literal percent sign | sprintf('%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 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
[ right] [left ] [00003.14] [*****stars] [+5] [-5] [tru]
A formatted report
<?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);
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 printf("%1\$s scored %2\$d points. Well done, %1\$s!\n", "Lena", 87); printf("%2\$s %1\$s\n", "world", "Hello");
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 $parts = [2026, 3, 9]; echo vsprintf("%04d-%02d-%02d", $parts), "\n"; fprintf(STDOUT, "%s has %d characters\n", "PHP", 3);
2026-03-09 PHP has 3 characters
number_format
For displaying numbers with thousands separators, number_format is simpler than printf:
<?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";
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 $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.
Sandwich 6.50 Juice 2.75 Cookie 1.80 ================== Subtotal 11.05 Tax 8% 0.88 Total 11.93