Зачем использовать функцию sprintf в PHP?

Я пытаюсь узнать больше о функции PHP sprintf (), но php.net не очень помогло мне, так как я все еще смущен, почему вы хотите использовать его?

взгляните на мой пример ниже.

зачем использовать это:

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

когда это делает то же самое и легче писать IMO:

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

Я что-то пропустил?

20 ответов


sprintf имеет все возможности форматирования исходного printf, что означает, что вы можете сделать гораздо больше, чем просто вставить значения переменных в строки.

например, укажите формат чисел (шестнадцатеричный, десятичный, восьмеричный), количество десятичных знаков, заполнение и многое другое. Google для printf и вы найдете множество примеров. The статья Википедии на printf должен заставить вас начать.


существует много вариантов использования sprintf, но один из способов их использования-это сохранение строки типа: "Привет, меня зовут %s" в базе данных или как константу в классе PHP. Таким образом, когда я хочу использовать эту строку я могу просто сделать это:

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

по сути, это позволяет некоторое разделение в коде. Если я использую "привет, Меня зовут %s" во многих местах моего кода, я могу изменить его на "%s-мое имя" в одном месте, и он обновляется везде автоматически, без необходимости каждый экземпляр и перемещение вокруг конкатенаций.


другое использование sprintf в локализованных приложениях в качестве аргументов sprintf не обязательно в том порядке, в котором они отображаются в строке формата.

пример:

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

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

но такой язык, как французский упорядочивает слова по-другому:

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

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

(Да, мой французский отстой: я выучил немецкий в школе!)

на самом деле, вы бы использовали gettext для хранения локализованных строк, но вы получаете идею.



это легче перевести.

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

строки перевода (gettext) теперь:

  • вот результат:
  • в этот день

при переводе на другой язык это может быть невозможно, или это приводит к очень странным предложениям.

теперь, если у вас есть

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

строки перевода (gettext) теперь:

  • вот результат: %S для этой даты %s

что имеет гораздо больше смысла, и гораздо более гибко переводить на другие языки


лучшая причина, которую я нашел, заключается в том, что она позволяет размещать все языковые строки в вашем языковом файле, когда люди могут переводить и заказывать их по мере необходимости, но вы все равно знаете, что независимо от формата строки - вы хотите показать имя пользователя.

например, ваш сайт скажет " Добро пожаловать обратно [[пользователь]]" в верхней части страницы. Как программист вы не знаете или care как ребята UI собираются написать это - вы просто знаете, что пользователи имя будет показано где-то в сообщении.

таким образом, вы можете встроить сообщение в свой код, не беспокоясь о том, что это сообщение на самом деле.

файл Lang (EN_US):

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

затем вы можете поддерживать любой тип сообщения на любом языке, используя это в своем фактическом php-коде.

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

Как уже упоминалось, он позволяет форматировать входные данные. Например, форсирование 2dp, 4-значных чисел и т. д. Это довольно полезно для построения строк запросов MySQL.

еще одно преимущество заключается в том, что он позволяет отделить макет строки от данных, подаваемых в нее, почти как подача в параматерах. Например, в случае запроса 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);

этот метод, конечно, имеет другие применения, например, при печати вывода в формате HTML, так далее.

Edit:по соображениям безопасности, при использовании техники, как указано выше вы должны очистить все входные переменные с помощью mysql_real_escape_string() перед использованием этого метода, чтобы предотвратить атаки вставки MySQL. если анализировать входные данные unsanitised, ваш сайт и сервер хакнут. (За исключением, конечно, переменных, которые были полностью построены вашим кодом и гарантированно безопасны.)


почему вы хотите использовать его?

это оказывается очень полезным при использовании (внешнего) источника для языковых строк. Если вам нужно фиксированное количество переменных в данной многоязычной строке, вам нужно только знать правильный порядок:

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

вставленные переменные даже не должны быть в начале или конце на нескольких языках, только их заказ.

конечно, вы можете написать свою собственную функцию для выполнения этой замены, несомненно, даже с некоторыми незначительными повышениями производительности, но это намного быстрее просто (учитывая, что у вас есть класс Language читать язык):

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

он также поставляется с полными возможностями printf, таким образом, также является однострочным для форматирования многочисленных типов переменных, например:


используя sprintf () намного чище и безопаснее форматировать строку.

например, когда вы имеете дело с входными переменными, это предотвращает неожиданные сюрпризы, указывая ожидаемый формат заранее (например, что вы ожидаете string [%s] или количество [%d]). Это может потенциально помочь с возможным риском SQL-инъекций, но это не помешает, если строка состоит из кавычек.

это также помогает иметь дело с поплавками вы можете явно указать точность цифр (например,%.2f), что избавляет вас от использования функций преобразования.

другими преимуществами является то, что большинство основных языков программирования имеют свои собственные реализации sprintf(), поэтому, как только вы познакомитесь с ним, его еще проще использовать, а не изучать новый язык (например, как объединить строки или преобразовать поплавки).

вкратце, это хорошая практика для использования, чтобы иметь более чистый и читаемый код.

например, см. ниже реальный пример:

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

или какой-то простой пример, который печатает, например,'1','2','3','4':

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

и печать с отформатированную строку:

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

здесь printf() эквивалентно sprintf(), но он выводит форматированную строку вместо ее возврата (в переменную).

что более читабельно?


даже я, хотя то же самое, если я им недавно пользовались. Когда вы создаете документы на основе данных пользователей это будет удобно.

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

который можно легко записать как

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

Это:

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

также может быть написано:

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

на мой взгляд, это яснее читать, но я вижу использование для локализации или форматирования.


некоторые из типичных случаев, когда вам нужен более точный контроль над форматом вывода. Например, может быть сложно убедиться, что определенное значение имеет определенное количество пробелов, заполненных спереди, в зависимости от его длины, или что число выводится в определенном точном формате.

есть много примеров в руководстве по PHP

также, что приходит к вашему примеру "легче писать".. Хотя эхо может быть проще писать, sprintf легче читать, особенно если у вас много переменных.

другой причиной использования sprintf или printf может быть то, что вы хотите, чтобы пользователь определил формат вывода некоторого значения - вы можете безопасно позволить им определить формат вывода, совместимый с sprintf.

О, и ваш пример на самом деле неверен для одной части. sprintf возвращает строку, но echo не - echo немедленно выводит его и ничего не возвращает, в то время как sprintf просто возвращает его.


  1. Если вы использовали C / C++, то вы будете использовать функцию sprintf.

  2. есть хороший шанс, что вторая линия менее эффективна. Echo разработан как команда вывода, в то время как sprintf предназначен для замены маркера строки. Я не PHP человек, но я подозреваю, что есть больше объектов, связанных с Эхом. Если он действует как Java, он создает новую строку каждый раз, когда что-то добавляется в список, поэтому вы в конечном итоге 4 создан строк.


иногда я получал что-то вроде этого, что я считаю немного более легким для чтения:

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

обычно я использую sprintf, чтобы убедиться, что идентификатор, полученный из пользовательского ввода, является целым числом, например:

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

также используется для создания рудиментарных шаблонов (для html-писем или других вещей), поэтому вы можете повторно использовать шаблон во многих местах:

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

очень полезно также форматировать числа в разных представлениях (восьмеричный, контролировать десятичное число и т. д.).


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

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

sprintf особенно полезен при форматировании строк, использующих числа. Например,

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

Output: There are -2 oranges in the basket

Oranges отформатирован как целое число (-2), но обернется к положительным числам, если использовать %u для значений без знака. Чтобы избежать такого поведения, я использую абсолютную функцию abs (), чтобы округлить число до нуля следующим образом:

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

Output: There are 5 oranges in the basket

конечный результат заявление с высокой удобочитаемостью, логической конструкцией, ясным форматированием, и гибкостью для добавление дополнительных переменных по мере необходимости. По мере увеличения числа переменных в сочетании с функциями, которые управляют этими переменными, преимущества становятся более очевидными. В качестве последнего примера:

$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

левая сторона оператора sprintf четко выражает строку и типы ожидаемых значений, в то время как правая сторона четко выражает используемые переменные и то, как ими манипулируют.


Ну sprintf имеет много возможностей, как мы знаем пример, как показано ниже:

несколько месяцев назад мне нужно было конвертировать секунды в формат hour:minute:seconds Как $t = 494050 //seconds Я хотел напечатать как 137 h 14 m 10 s поэтому я придумал функцию php springf() Я просто держу секунды в $t и echo sprintf("%02d h %s%02d m %s%02d s", floor($t/3600), $f, ($t/60)%60, $f, $t%60); дает мне 137 h 14 m 10 s

функция sprintf () очень полезна, если мы знаем, как ее использовать.


аргумент тот же для использования шаблонов. Вы захотите отделить Textsleev от фактических значений переменных. Помимо дополнительных возможностей sprintf, о которых мы упоминали, это просто стиль.


действительно хороший вариант использования для использования sprintf выводит мягкие форматы чисел, а также при смешивании разных типов в строке. Это может быть проще читать во многих случаях и делает его очень простым для печати различных представлений одной и той же переменной, особенно числовых.


использование функции sprintf () по сравнению с обычной конкатенацией имеет то преимущество, что вы можете применять различные типы форматирования к объединяемым переменным.

в вашем случае, у вас есть

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

и

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

давайте $result = 'passed'; date = '23rd';

используя обычную конкатенацию, вы можете получить только вывод:

Here is the result: passed for this date 23rd
если вы используете sprintf() вы можете получить модифицированный вывод такой as:
$output = sprintf('Here is the result: %.4s for this date %.2s',$result,$date);
echo $output;

выход:

Here is the result: pass for this date 23