PHP 8.0: New * precision and width modifiers in printf

TypeNew Feature

printf and its related functions (such as sprintf) in PHP 8.0 support specifying the width/precision modifiers as a function parameter rather than hard-coding it to the format string itself.

  • %f, the float formatter supports specifying the precision with %.3f, where the float is represented with a precision of 3. Similarly, %.5f is for precision 5, etc.
  • %s, the string formatter supports specifying the length of the string. %.5 would limit the string to 5 bytes, %.10s is for the first 10 bytes, etc.

In PHP 8, the width and precision modifiers can be set as a parameter to the printf and other related functions. The width/precision modifier is indicated with *, and should follow the same sequential order the printf functions otherwise accept.

printf('%.*f', 3, 1.61803); // "1.618"
printf('%.3f', 1.61803); // "1.618"

In the snippet above, the first printf call uses %.*f format, and the precision is set as the second parameter. The result is identical to the second printf call, where the precision is already specified in the format itself.

Positional parameters support the * modifiers as well:

printf('%.*2$f', 1.61803, 3);           // "1.618"
      //   ^^             ^

printf('%3$.*4$f', 42, 42, 1.61803, 3); // "1.618"
      //     ^^                     ^

Precision must me an integer

Note that the precision must be an integer, and there is no type coercion even with strict typing is off. Attempting to set a precision with any value other than an integer will throw a ValueError exception.

printf('%.*f', (string) 3, 1.618);
// Fatal error: Uncaught ValueError: Precision must be an integer in ...:...

Precision -1 is allowed in %g/%G and [%h/%H]

%g/%G and %h/%H specifiers allow -1 as the precision. For width and precision modifiers, only 0 and positive integers are allowed otherwise.

Backwards Compatibility Impact

Precision modifier and width modifiers are not understood in PHP versions prior to 8.0. They will not raise any warnings or exceptions.

Both width (%*) and precision (%.*) will be evaluated to empty strings.

PHP < 8.0 PHP >= 8.0
printf('%.*f', 3, 1.61803) f 1.618
printf('%.3f', 1.61803) 1.618 1.618
printf('%*.*f', 7, 3, 1.61803) .*f   1.618
printf('%7.3f', 1.61803)   1.618   1.618
printf('%*d', 5, 17) d    17
printf('%5d', 17)    17    17

The * modifiers are merely syntactic changes, and hardcoding the precision/width values in the format string itself ensures backwards compatibility with PHP versions prior to 8.0.

Related Changes