Why use sprintf function in PHP?

PhpPrintf

Php Problem Overview


I am trying to learn more about the PHP function sprintf() but php.net did not help me much as I am still confused, why would you want to use it?

Take a look at my example below.

Why use this:

$output = sprintf("Here is the result: %s for this date %s", $result, $date);

When this does the same and is easier to write IMO:

$output = 'Here is the result: ' .$result. ' for this date ' .$date;

Am I missing something here?

Php Solutions


Solution 1 - Php

sprintf has all the formatting capabilities of the original printf which means you can do much more than just inserting variable values in strings.

For instance, specify number format (hex, decimal, octal), number of decimals, padding and more. Google for printf and you'll find plenty of examples. The wikipedia article on printf should get you started.

Solution 2 - Php

There are many use cases for sprintf but one way that I use them is by storing a string like this: 'Hello, My Name is %s' in a database or as a constant in a PHP class. That way when I want to use that string I can simply do this:

$name = 'Josh';
// $stringFromDB = 'Hello, My Name is %s';
$greeting = sprintf($stringFromDB, $name);
// $greetting = 'Hello, My Name is Josh'

Essentially it allows some separation in the code. If I use 'Hello, My Name is %s' in many places in my code I can change it to '%s is my name' in one place and it updates everywhere else automagically, without having to go to each instance and move around concatenations.

Solution 3 - Php

Another use of sprintf is in localized applications as the arguments to sprintf don't have to be in the order they appear in the format string.

Example:

$color = 'blue';
$item = 'pen';

sprintf('I have a %s %s', $color, $item);

But a language like French orders the words differently:

$color = 'bleu';
$item = 'stylo';

sprintf('J\'ai un %2$s %1$s', $color, $item);

(Yes, my French sucks: I learned German in school!)

In reality, you'd use gettext to store the localized strings but you get the idea.


Solution 4 - Php

It's easier to translate.

echo _('Here is the result: ') . $result . _(' for this date ') . $date;

Translation (gettext) strings are now:

  • Here is the result:
  • for this date

When translated to some other language it might be impossible or it results to very weird sentences.

Now if you have

echo sprintf(_("Here is the result: %s for this date %s"), $result, $date);

Translation (gettext) strings is now:

  • Here is the result: %s for this date %s

Which makes much more sense and it's far more flexible to translate to other languages

Solution 5 - Php

The best reason that I have found is that it allows you to place all the language strings in your language file were people can translate and order them as needed - yet you still know that no matter what format the string is in - you wish to show the users name.

For example, your site will say "Welcome back [[User]]" on the top of the page. As the programmer you don't know or care how the UI guys are going to write that - you just know that a users name is going to be shown somewhere in a message.

So you do can embed the message into your code without worring about what that message actually is.

Lang file (EN_US):

...
$lang['welcome_message'] = 'Welcome back %s';
...

Then you can support any type of message in any language by using this in your actual php code.

sprintf($lang['welcome_message'], $user->name())

Solution 6 - Php

> why would you want to use it?

It proves very useful when using an (external) source for language strings. If you need a fixed number of variables in a given multilingual string, you only need to know the correct ordering:

en.txt

not_found    = "%s could not be found."
bad_argument = "Bad arguments for function %s."
bad_arg_no   = "Bad argument %d for function %s."

hu.txt

not_found    = "A keresett eljárás (%s) nem található."
bad_argument = "Érvénytelen paraméterek a(z) %s eljárás hívásakor."
bad_arg_no   = "Érvénytelen %d. paraméter a(z) %s eljárás hívásakor."

The inserted variables don't even have to be at the beginning or the end across multiple languages, only their ordering matters.

Of course, you could write your own function to perform this replace, undoubtedly even with some minor performance increases, but it is much faster to just (given you have a class Language to read language strings):

/**
 * throws exception with message($name = "ExampleMethod"):
 *  - using en.txt: ExampleMethod could not be found.
 *  - using hu.txt: A keresett eljárás (ExampleMethod) nem található.
 */
throw new Exception(sprintf(Language::Get('not_found'), $name));

/**
 * throws exception with message ($param_index = 3, $name = "ExampleMethod"):
 *  - using en.txt: Bad argument 3 for function ExampleMethod.
 *  - using hu.txt: Érvénytelen 3. paraméter a(z) ExampleMethod eljárás hívásakor.
 */
throw new Exception(sprintf(Language::Get('bad_arg_no'), $param_index, $name));

It also comes with the full capabilities of printf, thus is also a one-liner for formatting numerous types of variables, for example:

Solution 7 - Php

As mentioned, it allows formatting of the input data. For example, forcing 2dp, 4-digit numbers, etc. It's quite useful for building MySQL query strings.

Another advantage is that it allows you to separate the layout of the string from the data being fed into it, almost like feeding in paramaters. For example, in the case of a MySQL query:

// For security, you MUST sanitise ALL user input first, eg:
$username = mysql_real_escape_string($_POST['username']); // etc.
// Now creating the query:
$query = sprintf("INSERT INTO `Users` SET `user`='%s',`password`='%s',`realname`='%s';", $username, $passwd_hash, $realname);

This method does of course have other uses, such as when printing output as HTML, etc.

Edit: For security reasons, when using a technique as above you must sanitise all input variables with mysql_real_escape_string() before using this method, to prevent MySQL insertion attacks. If you parse unsanitised input, your site and server will get hacked. (With exception to, of course, variables which have been completely constructed by your code and are guaranteed to be safe.)

Solution 8 - Php

Using sprintf() is much cleaner and safer to format your string.

For example when you're dealing with input variables, it prevents unexpected surprises by specifying the expected format in advance (for instance, that you're expecting string [%s] or the number [%d]). This could potentially helps with possible risk of SQL injection, but it won't prevent if string consist quotes.

It also helps dealing with floats, you can explicitly specify the digit precision (e.g. %.2f) which saves you from using converting functions.

The other advantages is that most of the major programming languages have their own implementation of sprintf(), so once you get familiar with it, it's even more easier to use, rather than learning a new language (like how to concatenate strings or converting the floats).

In summary, it's a good practise to use in order to have a cleaner and more readable code.

For instance, see the below real example:

$insert .= "('".$tr[0]."','".$tr[0]."','".$tr[0]."','".$tr[0]."'),";

Or some simple example which prints e.g. '1','2','3','4':

print "foo: '" . $a . "','" . $b . "'; bar: '" . $c . "','" . $d . "'" . "\n";

and printing with formatted string:

printf("foo: '%d','%d'; bar: '%d','%d'\n", $a, $b, $c, $d);

where printf() is equivalent to sprintf(), but it outputs a formatted string instead of returning it (to the variable).

Which is more readable?

Solution 9 - Php

Even i though the same thing unless i used it recently. When you generate documents based on user inputs this will be in handy.

"<p>Some big paragraph ".$a["name"]." again have tot ake care of space and stuff .". $a["age"]. "also would be hard to keep track of punctuations and stuff in a really ".$a["token"]. paragarapoh.";

WHich can be easily written as

sprintf("Some big paragraph %s. Again have to take care of space and stuff.%s also wouldnt be hard to keep track of punctuations and stuff in a really %s paragraph",$a,$b,$c);

Solution 10 - Php

This:

"<p>Some big paragraph ".$a["name"]." again have to take care of space and stuff .". $a["age"]. "also would be hard to keep track of punctuations and stuff in a really ".$a["token"]. paragraph.";

Could also be written:

"<p>Some big paragraph {$a['name']} again have to take care of space and stuff .{$a['age']} also would be hard to keep track of punctuations and stuff in a really {$a['token']} paragraph.";

In my opinion this is clearer to read, but I can see the use for localizing, or formatting.

Solution 11 - Php

Some of the typical cases are where you need more precise control over the output format. It can be tricky to for example make sure a specific value has specific amount of spaces padded to front, depending on its length, or that a number is outputted in a specific precise format.

There are plenty of examples in the PHP manual

Also what comes to your example of "easier to write".. While the echo may be easier to write, the sprintf is easier to read, especially if you have a lot of variables.

Another reason to use sprintf or printf might be that you want to let a user define the output format of some value - you can safely allow them to define a sprintf compatible output format.

Oh, and your example is actually wrong for one part. sprintf returns the string, but echo does not - echo immediately outputs it and returns nothing, while sprintf just returns it.

Solution 12 - Php

  1. If you've used C/C++, then you would be used to the sprintf function.

  2. There is a good chance that the second line is less efficient. Echo is designed as an output command, whereas sprintf is designed to do string token substitution. I'm not a PHP person, but I suspect that there are more objects involved with the echo. If it acts like Java would, it creates a new string each time something is added to the list, so you'd end up with 4 strings created.

Solution 13 - Php

I usually use sprintf to ensure that a id that come from the user input is an integer for example:

// is better use prepared statements, but this is practical sometimes
$query = sprintf("SELECT * from articles where id = %d;",$_GET['article_id']);

Also is used to do rudimentary templates (for html mails or other things), so you can reuse a the the template in many places:

$mail_body = "Hello %s, ...";
$oneMail = sprintf($mail_body, "Victor");
$anotherMail = sprintf($mail_body, "Juan");

It's very useful also to format numbers in different representations (octal, control the decimal place, etc).

Solution 14 - Php

sprintf is particularly useful when formatting strings that use numbers. For example,

$oranges = -2.34;
echo sprintf("There are %d oranges in the basket", $oranges);

Output: There are -2 oranges in the basket

Oranges is formatted as a whole number (-2), but will wrap around to positive numbers if one uses %u for unsigned values. To avoid this behaviour, I use the absolute function, abs(), to round the number towards zero as follows:

$oranges = -5.67;
echo sprintf("There are %d oranges in the basket", abs($oranges));

Output: There are 5 oranges in the basket

The end result is a statement with high readability, logical construction, clear formatting, and flexibility for addition of additional variables as required. As the number of variables increases in combination with functions that manipulate these variables, the benefits become more apparent. As a final example:

$oranges = -3.14;
$apples = 1.5;
echo sprintf("There are %d oranges and %d apples", abs($oranges), abs($apples));

Output: There are 3 oranges and 4 apples

The left side of the sprintf statement clearly expresses the string and the types of expected values, while the right side clearly expressed the variables used and how they are being manipulated.

Solution 15 - Php

Well, sprintf has many capabilities as we know an example as below:

Few months ago I was in need of converting seconds to hour:minute:seconds format Like $t = 494050 //seconds i wanted to print like 137 h 14 m 10 s so i came up with the php function springf() i just hold the seconds in $t and echo sprintf("%02d h %s%02d m %s%02d s", floor($t/3600), $f, ($t/60)%60, $f, $t%60); gives me 137 h 14 m 10 s

sprintf() function is very useful one if we know how to use it.

Solution 16 - Php

Sometimes I got something like this, which I consider a little more easier to read:

$fileName = sprintf('thumb_%s.%s', 
                    $fileId,
                    $fileInfo['extension']);

Solution 17 - Php

define('TEXT_MESSAGE', 'The variable "%s" is in the middle!');

sprintf(TEXT_MESSAGE, "Var1");
sprintf(TEXT_MESSAGE, "Var2");
sprintf(TEXT_MESSAGE, "Var3");

Solution 18 - Php

The argument is the same one for using templates. You'll want to separate your Textsleev from the actual variable values. Besides the additional powers of sprintf that we're mentioned about it's just a style thing.

Solution 19 - Php

A really good use case for using sprintf is outputting padded formats of numbers and also, when mixing different types in a string. It can be easier to read in many cases and makes it super simple to print different representations of the same variable, especially numerical ones.

Solution 20 - Php

Using sprintf() function over ordinary concatenation has the advantage that you can apply different types of formatting on the variables to be concatenated.

In your case, you have

$output = sprintf("Here is the result: %s for this date %s", $result, $date);

and

$output = 'Here is the result: ' .$result. ' for this date ' .$date;

Let us take $result = 'passed'; date = '23rd';

Using ordinary concatenation you can only get the output:

Here is the result: passed for this date 23rd

However if you use sprintf() you can get a modified output such as:

$output = sprintf('Here is the result: %.4s for this date %.2s',$result,$date);
echo $output;

Output:

Here is the result: pass for this date 23

Solution 21 - Php

sprintf() is quite similar to printf(). If you know printf() in details then sprintf() and even vsprintf() is not really difficult to understand.

one of the things that differs sprintf() from printf() is that you will need declare a variable to catch the output from the function as it does not directly print/echo anything. Let see the following code snippets:

printf("Hello %s", "world"); // "Hello world"

sprintf("Hello %s", "world"); // does not display anything

echo sprintf("Hello %s", "world"); // "Hello world"

$a = sprintf("Hello %s", "world"); // does not display anything

echo $a;// "Hello world"

Hope that helps.

Solution 22 - Php

One "outputs", the other "returns", that's one of the main differences.

printf() Outputs

sprintf() Returns

Solution 23 - Php

You have to be careful when using sprintf in loops:

$a = 'Anton';
$b = 'Bert';
$c = 'Corni';
$d = 'Dora';
$e = 'Emiel';
$f = 'Falk';
$loops = 10000000;

$time = microtime(true);

for ($i = 0; $i < $loops; $i++)
{
    $test = $a . $b . $c . $d . $e . $f;
}

$concatTime = microtime(true) - $time;

$time = microtime(true);

for ($i = 0; $i < $loops; $i++)
{
    $test = "$a $b $c $d $e $f";
}

$concat2Time = microtime(true) - $time;

$time = microtime(true);

for ($i = 0; $i < $loops; $i++)
{
    $test = sprintf('%s %s %s %s %s %s', $a, $b, $c, $d, $e, $f);
}

$sprintfTime = microtime(true) - $time;

echo 'Loops: ' . $loops . '<br>';
echo '\'$a . $b . $c . $d . $e . $f\'' . ' needs ' . $concatTime  . 's<br>';
echo '"$a $b $c $d $e $f"' . ' needs ' . $concat2Time  . 's<br>';
echo 'sprintf(\'%s %s %s %s %s %s\', $a, $b, $c, $d, $e, $f)' . ' needs ' . $sprintfTime  . 's<br>';

Which leads to the following times (on my local machine with PHP 7.2):

Loops: 10000000

'$a . $b . $c . $d . $e . $f' needs 1.4507689476013s

"$a $b $c $d $e $f" needs 1.9958319664001s

sprintf('%s %s %s %s %s %s', $a, $b, $c, $d, $e, $f) needs 9.1771278381348s

Solution 24 - Php

I use it for messages to users or other "pretty" types of functionality. For instance if I know I'm going to use the user's name.

$name = 'Some dynamic name';

And have multiple messages to use in that situation. (I.e., blocking or following another user)

$messageBlock = 'You have blocked %s from accessing you.';
$messageFollow = 'Following %s is a great idea!';

You can create a general function that does something to the user and add this string, and no matter what the structure of the sentence it should look pretty nice. I always dislike just appending strings together and constantly using dot notation and closing and reopening strings just to make a sentence look good. I was a fan at first like most but this seems pretty useful when multiple strings need to be manipulated and you do not want to hard code the placement of the variable in every time.

Think of it, what looks better?

return $messageOne === true ? $name.'. Please use the next example' : 'Hi '.$name.', how are you?'

Or

$message = $messageOne === true ? 'Option one %s' 
: ($messageTwo === true ? 'Option Two %s maybe?' : '%s you can choose from tons of grammatical instances and not have to edit variable placement and strings');

return sprintf($message, $name);

Sure its an extra step but what if your conditional checks do a bunch of other functional things, then the quotations and appending starts to get in the way of coding functionally.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJasonDavisView Question on Stackoverflow
Solution 1 - PhpIsak SavoView Answer on Stackoverflow
Solution 2 - PhpjoshwbrickView Answer on Stackoverflow
Solution 3 - PhpKen KeenanView Answer on Stackoverflow
Solution 4 - PhpraspiView Answer on Stackoverflow
Solution 5 - PhpXeoncrossView Answer on Stackoverflow
Solution 6 - PhpJohn WeiszView Answer on Stackoverflow
Solution 7 - PhpSamuel JaeschkeView Answer on Stackoverflow
Solution 8 - PhpkenorbView Answer on Stackoverflow
Solution 9 - PhpswordfishView Answer on Stackoverflow
Solution 10 - PhpThomas TremainView Answer on Stackoverflow
Solution 11 - PhpJani HartikainenView Answer on Stackoverflow
Solution 12 - PhpPaulView Answer on Stackoverflow
Solution 13 - PhpCastroView Answer on Stackoverflow
Solution 14 - PhpRo McView Answer on Stackoverflow
Solution 15 - PhpSahedView Answer on Stackoverflow
Solution 16 - PhpviseView Answer on Stackoverflow
Solution 17 - PhpMeeView Answer on Stackoverflow
Solution 18 - PhpworengaView Answer on Stackoverflow
Solution 19 - PhpLloyd MooreView Answer on Stackoverflow
Solution 20 - Phpuser8241064View Answer on Stackoverflow
Solution 21 - PhpVuongView Answer on Stackoverflow
Solution 22 - PhpMohd Abdul MujibView Answer on Stackoverflow
Solution 23 - Phpg3rdnView Answer on Stackoverflow
Solution 24 - PhpDouglas RichardsonView Answer on Stackoverflow