13

Is there an equivalent of Python str.format in PHP?

In Python:

"my {} {} cat".format("red", "fat")

All I see I can do in PHP natively is by naming the entries and using str_replace:

str_replace(array('{attr1}', '{attr2}'), array('red', 'fat'), 'my {attr1} {attr2} cat')

Is there any other PHP's native alternatives?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
jeromej
  • 10,508
  • 2
  • 43
  • 62

3 Answers3

11

sprintf is the closest thing. It's the old-style Python string formatting:

sprintf("my %s %s cat", "red", "fat")
Blender
  • 289,723
  • 53
  • 439
  • 496
8

As PHP doesn't really have a proper alternative to str.format in Python, I decided to implement my very simple own which as most of the basic functionnalitites of the Python's one.

function format($msg, $vars)
{
    $vars = (array)$vars;

    $msg = preg_replace_callback('#\{\}#', function($r){
        static $i = 0;
        return '{'.($i++).'}';
    }, $msg);

    return str_replace(
        array_map(function($k) {
            return '{'.$k.'}';
        }, array_keys($vars)),

        array_values($vars),

        $msg
    );
}

# Samples:

# Hello foo and bar
echo format('Hello {} and {}.', array('foo', 'bar'));

# Hello Mom
echo format('Hello {}', 'Mom');

# Hello foo, bar and foo
echo format('Hello {}, {1} and {0}', array('foo', 'bar'));

# I'm not a fool nor a bar
echo format('I\'m not a {foo} nor a {}', array('foo' => 'fool', 'bar'));
  1. The order doesn't matter,
  2. You can omit the name/number if you want it to simply increment (the first {} matched will be transformed into {0}, etc),
  3. You can name your parameters,
  4. You can mix the three other points.
jeromej
  • 10,508
  • 2
  • 43
  • 62
  • what happens when you want to output a pair of curly-braces without it being interpreted as a placeholder for a variable? – dreftymac Jun 22 '17 at 19:24
  • @dreftymac A simple fix would be to match on `(?<!\{)\{\}(?!\})` instead of just `\{\}` (negative look behind/ahead) so `{{}}` isn't being matched then replace all `{{}}` with `{}`. (Sadly it will also leave behind `{{}` and `{}}` but that's fine, right?). Tell me if I should edit my code to reflect that. – jeromej Jun 24 '17 at 16:33
  • no problem, I guess the basic point I was trying to make is that replicating str.format() in PHP is not a trivial task. – dreftymac Jun 24 '17 at 17:09
  • 1
    I mostly needed its basic usages and I'm pretty pleased with how concise it turned out but it sure isn't exhaustive. :) Didn't claim it was. Thanks for your input. – jeromej Jun 24 '17 at 19:43
1

I know it's an old question, but I believe strtr with replace pairs deserves to be mentioned:

(PHP 4, PHP 5, PHP 7)

strtr — Translate characters or replace substrings

Description:

strtr ( string $str , string $from , string $to ) : string
strtr ( string $str , array $replace_pairs ) : string
<?php
var_dump(
strtr(
    "test {test1} {test1} test1 {test2}",
    [
        "{test1}" => "two",
        "{test2}" => "four",
        "test1" => "three",
        "test" => "one"
    ]
));

?>

this code would output:

string(22) "one two two three four" 

Same output is generated even if you change the array items order:

<?php
var_dump(
strtr(
    "test {test1} {test1} test1 {test2}",
    [
        "test" => "one",
        "test1" => "three",
        "{test1}" => "two",
        "{test2}" => "four"
    ]
));

?>

string(22) "one two two three four"
Savvas Radevic
  • 543
  • 1
  • 8
  • 23
  • 2
    Since the signature is super equivalent to the `str_replace` one, here is a list of differences between the two methods if someone is interested: https://stackoverflow.com/a/8177376/1524913 – jeromej Aug 06 '20 at 10:33