web-dev-qa-db-fra.com

Pourquoi utiliser la fonction sprintf en PHP?

J'essaie d'en apprendre plus sur la PHP function sprintf () mais php.net ne m'a pas beaucoup aidé, car je suis encore confus. Pourquoi voudriez-vous l'utiliser?

Jetez un oeil à mon exemple ci-dessous.

Pourquoi utiliser ceci:

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

Quand cela fait la même chose et qu'il est plus facile d'écrire IMO:

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

Est-ce que j'ai râté quelque chose?

183
JasonDavis

sprintf possède toutes les fonctionnalités de formatage de printf original, ce qui signifie que vous pouvez faire beaucoup plus que simplement insérer des valeurs de variable dans des chaînes.

Par exemple, spécifiez le format numérique (hexadécimal, décimal, octal), le nombre de décimales, le remplissage, etc. Google pour printf et vous trouverez de nombreux exemples. Le article de wikipedia sur printf devrait vous aider à démarrer.

125
Isak Savo

Il existe de nombreux cas d'utilisation de sprintf, mais je peux les utiliser en stockant une chaîne telle que: 'Bonjour, mon nom est% s' dans une base de données ou sous la forme d'une constante dans un PHP Ainsi, lorsque je veux utiliser cette chaîne, je peux simplement faire ceci:

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

Essentiellement, cela permet une certaine séparation dans le code. Si j'utilise 'Bonjour, mon nom est% s' dans de nombreux endroits de mon code, je peux le remplacer par '% s est mon nom' à un endroit et il se met à jour automatiquement ailleurs, sans avoir à consulter chaque instance et à vous déplacer. concaténations.

76
macinjosh

sprintf est une autre utilisation des applications localisées, car les arguments de sprintf ne doivent pas nécessairement être dans l’ordre dans lequel ils apparaissent dans la chaîne de formatage.

Exemple:

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

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

Mais une langue comme le français ordonne les mots différemment:

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

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

(Oui, mon français craint: j'ai appris l'allemand à l'école!)

En réalité, vous utiliseriez gettext pour stocker les chaînes localisées mais vous avez l’idée.


46
Ken Keenan

C'est plus facile à traduire.

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

Les chaînes de traduction (gettext) sont maintenant:

  • Voici le résultat:
  • pour cette date

Lorsque traduit dans une autre langue, cela peut être impossible ou il en résulte des phrases très étranges.

Maintenant si vous avez

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

Translation (gettext) strings est maintenant:

  • Voici le résultat:% s pour cette date% s

Ce qui est beaucoup plus logique et beaucoup plus flexible pour traduire dans d'autres langues

36
raspi

La meilleure raison que j’ai trouvée est que cela vous permet de placer toutes les chaînes de langue dans votre fichier de langue lorsque les utilisateurs peuvent les traduire et de les commander au besoin - mais vous savez toujours que, quel que soit le format de la chaîne, vous souhaitez afficher le nom de l'utilisateur.

Par exemple, votre site indiquera "Bienvenue [[Utilisateur]]" en haut de la page. En tant que programmeur, vous ne savez pas ni vous souciez de la façon dont les utilisateurs de l'interface utilisateur vont écrire cela - vous savez simplement qu'un nom d'utilisateur va être affiché. quelque part dans un message.

Vous pouvez donc intégrer le message dans votre code sans vous inquiéter de la nature de ce message.

Fichier Lang (EN_US):

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

Ensuite, vous pouvez prendre en charge n’importe quel type de message dans n’importe quelle langue en l’utilisant dans votre code php actuel.

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

pourquoi voudriez-vous l'utiliser?

Cela s'avère très utile lorsque vous utilisez une source (externe) pour des chaînes de langage. Si vous avez besoin d'un nombre fixe de variables dans une chaîne multilingue donnée, il vous suffit de connaître le bon ordre:

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."

Les variables insérées n'ont même pas besoin d'être au début ou à la fin dans plusieurs langues, seul leur classement est important.

Bien sûr, vous pouvez écrire votre propre fonction pour effectuer ce remplacement, même avec des augmentations de performances mineures, mais il est beaucoup plus rapide de simplement (étant donné que vous avez une classe Language pour lire les chaînes de langage) :

/**
 * 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));

Il est également livré avec toutes les fonctionnalités de printf, ce qui en fait un support unique pour le formatage de nombreux types de variables, par exemple:

9
John Weisz

Comme mentionné, il permet de formater les données d'entrée. Par exemple, forcer 2dp, nombres à 4 chiffres, etc. C'est très utile pour construire des chaînes de requête MySQL.

Un autre avantage est que cela vous permet de séparer la disposition de la chaîne des données qui y sont introduites, presque comme si vous importiez des paramètres. Par exemple, dans le cas d'une requête MySQL:

// 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);

Cette méthode a bien sûr d'autres utilisations, telles que l'impression HTML, etc.

Edit: Pour des raisons de sécurité, lorsque vous utilisez une technique comme ci-dessus vous devez nettoyer toutes les variables d'entrée avec mysql_real_escape_string() avant d'utiliser cette méthode, pour empêcher les attaques par insertion MySQL . Si vous analysez les entrées non normalisées, votre site et votre serveur seront piratés. (À l'exception, bien sûr, des variables qui ont été entièrement construites par votre code et dont la sécurité est garantie.)

8
Samuel Jaeschke

Utiliser sprintf () est beaucoup plus propre et plus sûr pour formater votre chaîne.

Par exemple, lorsque vous traitez avec des variables d’entrée, cela évite les surprises inattendues en spécifiant le format attendu à l’avance (par exemple, vous attendez chaine [%s] Ou le nombre [%d ]). Cela pourrait potentiellement aider avec un risque potentiel de injection SQL , mais cela n'empêchera pas les guillemets.

Il est également utile de gérer les flottants. Vous pouvez spécifier explicitement la précision des chiffres (par exemple, %.2f), Ce qui vous évite d’utiliser des fonctions de conversion.

L’autre avantage est que la plupart des principaux langages de programmation ont leur propre implémentation de sprintf(), donc une fois que vous vous y êtes familiarisé, il est encore plus facile à utiliser que d’apprendre un nouveau langage (comme comment concaténer chaînes de caractères ou la conversion des flotteurs).

En résumé, il est recommandé d’utiliser un code plus propre et plus lisible.

Par exemple, voir ci-dessous exemple réel :

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

Ou un exemple simple qui imprime, par exemple, '1','2','3','4':

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

et imprimer avec une chaîne formatée:

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

printf() équivaut à sprintf(), mais génère une chaîne formatée au lieu de la renvoyer (à la variable).

Lequel est le plus lisible?

6
kenorb

Même si je pensais la même chose à moins que je ne l'utilise récemment. Lorsque vous générez des documents en fonction des entrées de l'utilisateur, cela vous sera utile.

"<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.";

Ce qui peut être facilement écrit comme

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);
4
swordfish

Cette:

"<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.";

Pourrait aussi être écrit:

"<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.";

À mon avis, cela est plus clair à lire, mais je peux voir l’utilisation de la localisation ou du formatage.

4
Thomas Tremain

Dans certains cas typiques, vous avez besoin d’un contrôle plus précis du format de sortie. Il peut être délicat, par exemple, de s’assurer qu’une valeur spécifique a une quantité spécifique d’espaces remplis à l’avant, en fonction de sa longueur, ou qu’un nombre est sorti dans un format précis.

Il y a beaucoup d'exemples dans le PHP manuel

Également ce qui vient à votre exemple de "plus facile à écrire" .. Alors que l'écho peut être plus facile à écrire, le sprintf est plus facile à lire, surtout si vous avez beaucoup de variables.

Une autre raison d'utiliser sprintf ou printf peut être que vous souhaitez laisser un utilisateur définir le format de sortie d'une valeur - vous pouvez lui permettre en toute sécurité de définir un format de sortie compatible avec sprintf.

Oh, et votre exemple est en fait faux pour une partie. sprintf renvoie la chaîne, mais echo ne le renvoie pas - echo la renvoie immédiatement et ne renvoie rien, tandis que sprintf la renvoie simplement.

3
Jani Hartikainen

J'utilise habituellement sprintf pour m'assurer qu'un identifiant provenant de l'entrée utilisateur est un entier, par exemple:

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

Est également utilisé pour faire des modèles rudimentaires (pour les mails html ou autres), afin que vous puissiez réutiliser le modèle dans de nombreux endroits:

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

Il est également très utile de formater des nombres dans différentes représentations (octal, contrôler la décimale, etc.).

3
Castro
  1. Si vous avez utilisé le C/C++, vous seriez habitué à la fonction sprintf.

  2. Il y a de bonnes chances que la deuxième ligne soit moins efficace. Echo est conçu comme une commande de sortie, alors que sprintf est conçu pour effectuer une substitution de jeton de chaîne. Je ne suis pas un PHP personne, mais je soupçonne qu'il y a plus d'objets impliqués dans l'écho. S'il agit comme Java le ferait, cela créerait une nouvelle chaîne à chaque fois que quelque chose est ajouté à la liste, vous allez vous retrouver avec 4 chaînes créées.

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

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

Parfois, j'ai quelque chose comme ça, que je considère un peu plus facile à lire:

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

Bien, sprintf possède de nombreuses fonctionnalités, comme l’exemple ci-dessous:

Il y a quelques mois, j'avais besoin de convertir les secondes en heure: minute: format de secondes Comme $t = 494050 //seconds je voulais imprimer comme 137 h 14 m 10 s donc je suis venu avec la fonction php springf() Je tiens juste les secondes dans $t et echo sprintf("%02d h %s%02d m %s%02d s", floor($t/3600), $f, ($t/60)%60, $f, $t%60); me donne 137 h 14 m 10 s

la fonction sprintf () est très utile si nous savons l’utiliser.

3
Sahed

sprintf est particulièrement utile lors du formatage de chaînes utilisant des nombres. Par exemple,

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

Output: There are -2 oranges in the basket

Les oranges sont présentées sous la forme d'un nombre entier (-2), mais se résument en nombres positifs si l'on utilise% u pour les valeurs non signées. Pour éviter ce comportement, j'utilise la fonction absolue abs () pour arrondir le nombre vers zéro de la manière suivante:

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

Output: There are 5 oranges in the basket

Le résultat final est une instruction avec une lisibilité élevée, une construction logique, un formatage clair et une flexibilité permettant d'ajouter des variables supplémentaires en fonction des besoins. À mesure que le nombre de variables augmente en combinaison avec les fonctions qui manipulent ces variables, les avantages deviennent plus évidents. Dernier exemple:

$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

Le côté gauche de l'instruction sprintf exprime clairement la chaîne et les types de valeurs attendues, tandis que le côté droit exprime clairement les variables utilisées et la manière dont elles sont manipulées.

3
Ro Mc

Un bon cas d'utilisation de sprintf consiste à sortir des formats de nombres remplis et également, lors du mélange de différents types dans une chaîne. Il peut être plus facile à lire dans de nombreux cas et simplifie énormément l’impression de différentes représentations de la même variable, notamment numériques.

2
Lloyd Moore

L'argument est le même pour l'utilisation de modèles. Vous voudrez séparer votre texte de la valeur réelle des variables. Outre les pouvoirs supplémentaires de sprintf dont nous avons parlé, il ne s'agit que d'une question de style.

2
worenga

L'utilisation de la fonction sprintf () sur la concaténation ordinaire présente l'avantage de pouvoir appliquer différents types de mise en forme sur les variables à concaténer.

Dans votre cas, vous avez

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

et

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

Prenons $result = 'passed'; date = '23rd';

En utilisant la concaténation ordinaire, vous ne pouvez obtenir que le résultat:

Here is the result: passed for this date 23rd

Cependant, si vous utilisez sprintf(), vous pouvez obtenir une sortie modifiée telle que:

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

Sortie:

Here is the result: pass for this date 23
2
user8241064

sprintf() est assez similaire à printf(). Si vous connaissez printf() en détail, alors sprintf() et même vsprintf() n'est pas vraiment difficile à comprendre.

une des choses qui diffère de sprintf() de printf() est que vous aurez besoin de déclarer une variable pour intercepter la sortie de la fonction car elle n’imprime ni n’écho directement. Voyons les extraits de code suivants:

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"

J'espère que ça t'as aidé.

1
Vuong

Je l'utilise pour les messages aux utilisateurs ou d'autres "jolies" fonctionnalités. Par exemple, si je sais que je vais utiliser le nom de l'utilisateur.

$name = 'Some dynamic name';

Et avoir plusieurs messages à utiliser dans cette situation. (C'est-à-dire bloquer ou suivre un autre utilisateur)

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

Vous pouvez créer une fonction générale qui fait quelque chose à l'utilisateur et ajouter cette chaîne. Quelle que soit la structure de la phrase, elle devrait être jolie. Je n'aime toujours pas simplement ajouter des chaînes ensemble et utiliser constamment la notation par points, ainsi que la fermeture et la réouverture de chaînes, juste pour que la phrase soit belle. Au début, j’étais un fan comme la plupart des gens, mais cela semble très utile lorsque plusieurs chaînes doivent être manipulées et que vous ne souhaitez pas coder en dur l’emplacement de la variable à chaque fois.

Pensez-y, quoi de mieux?

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

Ou

$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);

C’est certes une étape supplémentaire, mais si vos vérifications conditionnelles remplissaient bien d’autres tâches fonctionnelles, les citations et les ajouts commençaient à entraver le codage fonctionnel.

0
Douglas Richardson

Vous devez faire attention lorsque vous utilisez sprintf dans les boucles:

$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>';

Ce qui conduit aux temps suivants (sur ma machine locale avec PHP 7.2)]:

Boucles: 10000000

'$ a. $ b. $ c. $ d. $ e. $ f 'nécessite 1.4507689476013s

"$ a $ b $ c $ d $ e $ f" a besoin de 1.9958319664001s

sprintf ('% s% s% s% s% s% s', $ a, $ b, $ c, $ d, $ e, $ f) nécessite 9.1771278381348s

0
g3rdn

L'un "produit", l'autre "renvoie", c'est l'une des principales différences.

printf() Sorties

sprintf() Retourne

0
Mohd Abdul Mujib