string.Format() in PHP @ r1
This article was originally published in my blog (affectionately referred to as blargh) on . The original blog no longer exists as I've migrated everything to this wiki.
The original URL of this post was at https://tmont.com/blargh/2010/1/string-format-in-php. Hopefully that link redirects back to this page.
.NET's sprintf()
equivalent
has ordered parameters.
C♯
var s = string.Format("My name is {1}, {0}", "Tommy", "Montgomery");
//s = "My name is Montgomery, Tommy"
var s = string.Format("My name is {{{0}}}", "Tommy");
//s = "My name is {Tommy}"
I needed that. Here it is, PHPified:
php
function format($format) {
$args = func_get_args();
$format = array_shift($args);
preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
$offset = 0;
foreach ($matches[1] as $data) {
$i = $data[0];
$format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i));
$offset += strlen(@$args[$i]) - 2 - strlen($i);
}
return $format;
}
There's a lot going on in here that isn't used very often in PHP. Here is a terse explanation of the not-so-obvious features:
-
The
PREG_OFFSET_CAPTURE
constant tells the regex engine to capture the string index offset of each match. -
(?=\{)
and(?!\})
in the regular expression are positive and negative lookarounds, respectively. The nice thing about that is they're also zero-width matching, which means they won't be returned as part of the match result. These are needed because to output a literal{
in a C# string you precede it with another{
(a little known fact about C#). -
substr_replace
is an infrequently used, extremely useful function, that replaces a substring within a string, expanding to the given width. -
The
$offset
variable tracks the string length delta. Since we're modifying the string, the offsets captured in the regex match becomes out of date.