Dlaczego warto używać funkcji sprintf w PHP?

Próbuję dowiedzieć się więcej o funkcji PHP sprintf (), ale php.net nie pomogło mi to, ponieważ nadal jestem zdezorientowany, dlaczego chcesz go użyć?

Spójrz na mój przykład poniżej.

Po co używać tego:

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

Kiedy to robi to samo i łatwiej jest napisać IMO:

$output = 'Here is the result: ' .$result. ' for this date ' .$date;
Czy coś mi umknęło?
 168
Author: JasonDavis, 2009-09-07

20 answers

sprintf posiada wszystkie możliwości formatowania oryginalnego printf, co oznacza, że możesz zrobić znacznie więcej niż tylko wstawianie wartości zmiennych w łańcuchach.

Na przykład określ format liczb (szesnastkowy, dziesiętny, ósemkowy), liczbę miejsc po przecinku, wypełnienie i inne. Google dla printf i znajdziesz wiele przykładów. Artykuł Wikipedii NA printf powinien zacząć.

 119
Author: Isak Savo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 20:13:37

Istnieje wiele przypadków użycia sprintf, ale jednym ze sposobów, w jaki ich używam, jest przechowywanie ciągu znaków: 'Hello, My Name is %s' w bazie danych lub jako stałej w klasie PHP. W ten sposób, gdy chcę użyć tego ciągu, mogę po prostu zrobić to:

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

Zasadniczo pozwala na pewne rozdzielenie kodu. Jeśli użyję 'Hello, My Name is %s' w wielu miejscach w kodzie, mogę zmienić go na '%s is my name ' w jednym miejscu i aktualizuje się wszędzie indziej automatycznie, bez konieczności przechodzenia do każdej instancji i poruszać się po konkatenacjach.

 73
Author: macinjosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 20:20:50

Inne użycie sprintf jest w lokalnych aplikacjach, ponieważ argumenty sprintf nie muszą być w kolejności, w jakiej występują w łańcuchu formatu.

Przykład:

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

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

Ale język taki jak francuski porządkuje słowa inaczej:

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

sprintf('J\'ai un %2$s %1$s', $color, $item);
(Tak, mój francuski jest do bani: uczyłem się niemieckiego w szkole!)

W rzeczywistości użyłbyś gettext do przechowywania zlokalizowanych łańcuchów, ale masz pomysł.


 42
Author: Ken Keenan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-19 22:46:12

Łatwiej to przetłumaczyć.

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

Tłumaczenie (gettext) ciągi są teraz:

  • oto wynik:
  • na tę datę

Przetłumaczone na inny język może być niemożliwe lub skutkować bardzo dziwnymi zdaniami.

Teraz jeśli masz

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

Tłumaczenie (gettext) ciągów jest teraz:

  • oto wynik: %s dla tej daty %s

Co ma o wiele większy sens i jest o wiele bardziej elastyczne w tłumaczeniu na inne języki

 35
Author: raspi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 22:09:07

Najlepszy powód, że znalazłem jest to, że pozwala umieścić wszystkie ciągi językowe w pliku językowym były ludzie mogą przetłumaczyć i zamówić je w razie potrzeby - ale nadal wiesz, że bez względu na to, w jakim formacie ciąg jest w-Chcesz pokazać nazwę użytkownika.

Na przykład, Twoja strona powie "Witamy z powrotem [[użytkownik]]" na górze strony. Jako programista nie wiesz ani nie dbasz jak faceci z UI to napiszą - po prostu wiesz, że nazwa użytkownika będzie być pokazane gdzieś w wiadomości.

Więc możesz osadzić wiadomość w kodzie, nie martwiąc się o to, czym jest ta wiadomość.

Plik Lang (EN_US):

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

Następnie możesz obsługiwać każdy rodzaj wiadomości w dowolnym języku, używając tego w swoim rzeczywistym kodzie php.

sprintf($lang['welcome_message'], $user->name())
 16
Author: Xeoncross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 21:59:58

Jak wspomniano, umożliwia formatowanie danych wejściowych. Na przykład wymuszanie liczb 2dp, 4-cyfrowych itp. Jest to bardzo przydatne do budowania ciągów zapytań MySQL.

Kolejną zaletą jest to, że pozwala oddzielić układ łańcucha znaków od wprowadzanych do niego danych, prawie jak karmienie w parametrach. Na przykład w przypadku zapytania 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);

Ta metoda ma oczywiście inne zastosowania, na przykład podczas drukowania wyjścia jako HTML, itp.

Edit: For ze względów bezpieczeństwa, używając powyższej techniki , przed użyciem tej metody należy wyczyścić wszystkie zmienne wejściowe za pomocąmysql_real_escape_string(), aby zapobiec atakom wstawiania MySQL. jeśli parsujesz dane wejściowe, Twoja strona i serwer zostaną zhakowane. (Z wyjątkiem, oczywiście, zmiennych, które zostały całkowicie skonstruowane przez Twój kod i są gwarantowane jako Bezpieczne.)

 8
Author: Samuel Jaeschke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-07 04:45:56
Dlaczego chcesz go użyć?

Okazuje się bardzo przydatny, gdy używa się (zewnętrznego) źródła łańcuchów językowych. Jeśli potrzebujesz stałej liczby zmiennych w danym wielojęzycznym łańcuchu, musisz tylko znać poprawną kolejność:

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

Wstawione zmienne nie muszą być na początku ani na końcu w wielu językach, liczy się tylko ich kolejność.

Oczywiście, ty można napisać własną funkcję do wykonania tego zastąpienia, bez wątpienia nawet przy niewielkim wzroście wydajności, ale znacznie szybciej jest po prostu (biorąc pod uwagę, że masz klasę Language do odczytu ciągów językowych):

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

Jest również wyposażony w pełne możliwości printf, dlatego jest również jednowierszowcem do formatowania wielu typów zmiennych, na przykład:

 8
Author: John Weisz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:46

Użycie sprintf () {[12] } jest znacznie czystsze i bezpieczniejsze formatowanie łańcucha.

Na przykład, gdy masz do czynienia ze zmiennymi wejściowymi, zapobiega to nieoczekiwanym niespodziankom, określając z wyprzedzeniem oczekiwany format (na przykład oczekujesz ciągu znaków [%s] lub liczby [%d]). Może to potencjalnie pomóc w możliwym ryzyku SQL injection , ale nie zapobiegnie, jeśli string consists cudzysłowy.

Pomaga również radzić sobie z pływakami, można wyraźnie określ dokładność cyfr (np. %.2f), która pozwoli Ci uniknąć użycia funkcji konwertujących.

Inną zaletą jest to, że większość głównych języków programowania ma własną implementację sprintf(), więc gdy już się z nią zapoznasz, jest jeszcze łatwiejsza w użyciu, niż uczenie się nowego języka (np. jak łączyć ciągi znaków lub konwertować pływaki).

Podsumowując, jest to dobra praktyka, aby mieć czystszy i bardziej czytelny kod.

Dla przykład, patrz poniżej prawdziwy przykład:

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

Lub jakiś prosty przykład, który wyświetla np. '1','2','3','4':

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

I drukowanie z sformatowanym ciągiem:

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

Gdzie {[8] } jest równoważne sprintf(), ale wypisuje sformatowany łańcuch znaków zamiast zwracać go (do zmiennej).

Który jest bardziej czytelny?

 6
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 14:50:23

Nawet ja myślałem to samo, chyba że ostatnio go używałem. Podczas generowania dokumentów na podstawie danych wejściowych użytkownika będzie to przydatne.

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

Które można łatwo zapisać jako

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
Author: swordfish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-30 09:18:24

To:

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

Można też napisać:

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

Moim zdaniem jest to bardziej czytelne, ale widzę zastosowanie do lokalizacji lub formatowania.

 4
Author: Thomas Tremain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-17 04:45:53

Niektóre z typowych przypadków wymagają dokładniejszej kontroli nad formatem wyjściowym. Może to być trudne, aby na przykład upewnić się, że określona wartość ma określoną ilość spacji wyściełanych do przodu, w zależności od jej długości, lub że liczba jest wyprowadzana w określonym, precyzyjnym formacie.

Istnieje wiele przykładów w instrukcji PHP

Również to, co przychodzi do twojego przykładu "łatwiej pisać".. Chociaż echo może być łatwiejsze do napisania, sprintf jest łatwiejszy do odczytania, zwłaszcza, jeśli masz wiele zmiennych.

Innym powodem używania sprintf lub printf może być to, że chcesz pozwolić użytkownikowi zdefiniować format wyjściowy o określonej wartości - możesz bezpiecznie zezwolić mu na zdefiniowanie formatu wyjściowego zgodnego ze sprintf.

A twój przykład jest z jednej strony zły. sprintf zwraca łańcuch, ale echo nie - echo natychmiast go wypisuje i nic nie zwraca, podczas gdy sprintf po prostu go zwraca.
 3
Author: Jani Hartikainen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 20:15:52
  1. Jeśli używałeś C / C++, to będziesz używany do funkcji sprintf.

  2. Istnieje duża szansa, że druga linia jest mniej wydajna. Echo jest zaprojektowane jako polecenie wyjściowe, podczas gdy sprintf jest zaprojektowany do zastępowania tokenów łańcuchowych. Nie jestem osobą PHP, ale podejrzewam, że jest więcej obiektów związanych z echem. Jeśli działa tak, jak w Javie, tworzy nowy ciąg znaków za każdym razem, gdy coś jest dodawane do listy, więc skończysz z 4 ciągami znaków stworzony.

 3
Author: Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 20:17:29

Czasami mam coś takiego, co uważam za nieco łatwiejsze do odczytania:

$fileName = sprintf('thumb_%s.%s', 
                    $fileId,
                    $fileInfo['extension']);
 3
Author: vise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 20:25:29

Zwykle używam sprintf, aby upewnić się, że id pochodzące z wejścia użytkownika jest liczbą całkowitą, na przykład:

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

Jest również używany do wykonywania podstawowych szablonów (do wiadomości html lub innych rzeczy), więc możesz ponownie użyć szablonu w wielu miejscach:

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

Bardzo przydatne jest również Formatowanie liczb w różnych reprezentacjach (ósemka, Kontrola miejsca po przecinku, itp.).

 3
Author: Castro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 22:13:35
define('TEXT_MESSAGE', 'The variable "%s" is in the middle!');

sprintf(TEXT_MESSAGE, "Var1");
sprintf(TEXT_MESSAGE, "Var2");
sprintf(TEXT_MESSAGE, "Var3");
 3
Author: Mee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-08 02:18:19

Sprintf jest szczególnie przydatny podczas formatowania łańcuchów, które używają liczb. Na przykład,

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

Output: There are -2 oranges in the basket

Pomarańcze jest sformatowane jako liczba całkowita (-2), ale będzie owijać się do liczb dodatnich, jeśli ktoś używa %u Dla niepodpisanych wartości. Aby uniknąć tego zachowania, używam funkcji absolutnej, abs (), aby zaokrąglić liczbę w kierunku zera w następujący sposób:

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

Output: There are 5 oranges in the basket

Efektem końcowym jest Oświadczenie o wysokiej czytelności, konstrukcji logicznej, przejrzystym formatowaniu i elastyczności dodawania dodatkowych zmienne wymagane. Wraz ze wzrostem liczby zmiennych w połączeniu z funkcjami, które manipulują tymi zmiennymi, korzyści stają się bardziej widoczne. Jako ostateczny przykład:

$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

Lewa strona instrukcji sprintf wyraźnie wyraża ciąg znaków i typy oczekiwanych wartości, podczas gdy prawa strona wyraźnie wyraża używane zmienne i sposób ich manipulowania.

 3
Author: Ro Mc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-15 11:57:55

Cóż, sprintf ma wiele możliwości, jak wiemy przykład jak poniżej:

Kilka miesięcy temu potrzebowałem konwersji sekund na format hour: minute: seconds Tak jak {[1] } chciałem wydrukować tak jak 137 h 14 m 10 s więc wymyśliłem funkcję php springf() po prostu trzymam sekundy w $t i echo sprintf("%02d h %s%02d m %s%02d s", floor($t/3600), $f, ($t/60)%60, $f, $t%60); daje mi 137 h 14 m 10 s

Funkcja Sprintf() jest bardzo przydatna, jeśli wiemy jak jej używać.

 3
Author: Sahed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-01 11:23:23

Argument jest taki sam dla użycia szablonów. Będziesz chciał oddzielić Textsleev od rzeczywistych wartości zmiennych. Poza dodatkowymi mocami sprintf, o których mówi się, to tylko styl.

 2
Author: worenga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-26 18:45:01

Naprawdę dobrym przykładem użycia sprintf jest wyprowadzanie wyściełanych formatów liczb, a także podczas mieszania różnych typów w łańcuchu. W wielu przypadkach może być łatwiejszy do odczytania i sprawia, że drukowanie różnych reprezentacji tej samej zmiennej, szczególnie liczbowej, jest bardzo proste.

 2
Author: Lloyd Moore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-11 22:09:07

Użycie funkcji sprintf () zamiast zwykłej konkatenacji ma tę zaletę, że można zastosować różne typy formatowania zmiennych, które mają być konkatenowane.

W Twoim przypadku masz

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

I

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

Weźmy $result = 'passed'; date = '23rd';

Używając zwykłej konkatenacji można uzyskać tylko wyjście:

Here is the result: passed for this date 23rd

Jeśli jednak użyjesz sprintf(), możesz uzyskać zmodyfikowane wyjście, takie jak:

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

Wyjście:

Here is the result: pass for this date 23
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-02 22:24:28