В PHP есть несколько вариантов указания строк, но большинство из нас знакомо только с их определением в кавычках. Иногда эти строки простые, и мы можем использовать их как есть, но чаще всего мы хотим, чтобы они были динамическими, связанными с различными переменными.
Важно иметь хорошее представление о том, как строки могут быть объединены с любой переменной.
Наиболее распространенные подходы к адаптации строк заключаются в использовании:
- Одинарные кавычки с конкатенацией
- Двойные кавычки с переменной в строке
- функции sprintf (vsprintf)
- синтаксис heredoc (newdoc)
Остановимся на каждом варианте — его сильных и слабых сторонах.
Сначала немного теории.
Теория
#1 Одинарные кавычки с конкатенацией
Строка в одинарных кавычках не содержит интерпретируемых переменных. В отличие от других параметров, переменные в строке с одинарными кавычками не будут расширены при появлении. Это означает, что необходимо использовать конкатенацию.
'Variable is' . $var;
#2 Двойные кавычки с переменной в строке
В случае двойных кавычек компилятор PHP будет расширять каждую переменную внутри строки следующим образом.
"Variable is {$var}";
#3 Функция sprintf (vsprintf)
Sprintf — самая мощная и продвинутая функция форматирования строк в PHP fi1a/format, предлагающая множество опций для управления конечным результатом. Он позволяет форматировать строки в соответствии со специальным языком шаблонов и кажется гораздо более мощным способом вставки в них переменных, но с наибольшими затратами времени на обработку.
Функция sprintf принимает строковый шаблон в качестве первого аргумента. За ним может следовать бесконечное количество аргументов — sprintf заменит заполнители в строке в соответствии с аргументами, которые вы передаете функции.
sprintf('Variable is %s', $var);
# 4 здесь документ (и сейчас документ)
Здесь документ определяется как раздел файла исходного кода, который обрабатывается так, как если бы он был отдельным файлом.
Улучшенный синтаксис (начиная с PHP 7.3) позволяет использовать heredoc более читаемым, понятным и менее подверженным ошибкам способом. Heredoc позволяет вам делать то, что сложнее сделать в кавычках. Позволяет определить блок текста как литерал.
По умолчанию PHP обрабатывает heredoc, как если бы это была строка в двойных кавычках, а nowdoc, как если бы это была строка в одинарных кавычках. Чтобы использовать nowdoc, просто поместите идентификатор открытия в одинарные кавычки.
синтаксис heredoc:
$str = <<<STR
Variable is $var
STR;
синтаксис нового документа:
$str = <<<'STR'
Variable is $var
STR;
Упражняться
Давайте проверим каждый подход на нескольких примерах.
Посмотрите на следующий текст:
Knock knock, "LANG" has you. Wake up NAME, ACTION
конкатенация №1
$str = 'Knock knock, "' . $lang . '" has you. Wake up ' . $name . ', ' . $action;
Здесь много кавычек, конкатенаций и лишних пробелов.
#2 Переменная в строке
$str = "Knock knock, \"{$lang}\" has you. Wake up {$name}, {$action}";
Это выглядит намного лучше. Только не забывайте предварять переменные и специальные символы символами (в данном случае — «).
#3 Спринтф
$str = sprintf('Knock knock, "%s" has you. Wake up %s, %s', $lang, $name, $action);
Это также выглядит вполне читабельно, без использования escape-символов.
При желании мы можем передать переменные в виде массива.
$vars = [
'PHP',
'Developer',
'time to code'
];
$str = sprintf('Knock knock, "%s" has you. Wake up %s, %s', ...$vars);
То же самое и с функцией vsprintf.
$str = vsprintf('Knock knock, "%s" has you. Wake up %s, %s', $vars);
#4 Вот документ
$str = <<<STR
Knock knock, "$lang" has you. Wake up $name, $action
STR;
Никаких побегов, конкатенаций или дополнительных кавычек, никаких вызовов функций, всего 3 строки простой строки.
Допустим, мы хотим добавить разметку с динамическими переменными:
<div class="container">
<p style="font-size:SIZEpx;line-height:SIZEpx;">
<span class="first-item" style="color:red">TEXT1</span>
<span class="last-item" style="color:black">TEXT2/span>
</p>
</div>
В этом случае мы рекомендуем использовать heredoc :
<<<TEXT
<div class="container">
<p style="font-size:{$size}px;line-height:{$size}px;">
<span class="first-item" style="color:red">$text1</span>
<span class="last-item" style="color:black">$text2</span>
</p>
</div>
TEXT;
Внутри строка выглядит аналогично, но нам нужно немного больше escape-символов — «\» и {}
"<div class=\"container\">
<p style=\"font-size:{$size}px;line-height:{$size}px;\">
<span class=\"first-item\" style=\"color:red\">{$text1}</span>
<span class=\"last-item\" style=\"color:black\">{$text2}</span>
</p>
</div>";
Конкатенация выглядит менее читабельно, но благодаря форматированию не раздражает. Однако главная проблема здесь не в этом:
'<div class="container">
<p style="font-size:' . $size . 'px;line-height:' . $size . 'px;">
<span class="first-item" style="color:red">' . $text1 . '</span>
<span class="last-item" style="color:black">' . $text2 . '</span>
</p></div>';
Представьте, что вы хотите добавить новую динамическую переменную в тег <p> в синтаксисе heredoc.
display: $display;
или в двойных кавычках
display: {$display};
В то время как с одинарными кавычками нам нужно найти правильное место, прежде чем добавлять больше конкатенаций и кавычек, здесь очень легко сделать ошибку.
display:' . $display . ';">' . '
И для спринта :
sprintf('<div class="container">
<p style="font-size:%spx;line-height:%spx;">
<span class="first-item" style="color:red">%s</span>
<span class="last-item" style="color:black">%s</span>
</p>
</div>', $size, $size, $text1, $text2);
Передача многострочной строки выглядит не очень хорошо, если только вы не хотите сначала присвоить ее какой-либо переменной.
Также помните, что количество переменных заполнителей должно быть небольшим. В противном случае вам будет трудно найти путь через 10+ параметров, пытаясь добавить новый %s, найти элемент в списке параметров и добавить его в вызов sprintf.
В приведенном выше примере, если мы хотим добавить новую переменную
display: %s;
сразу после высоты строки нам нужно определить, что это третий параметр, и передать его в качестве аргумента между $size и $text1 . Разве это не звучит хорошо?
В этом случае вы можете попробовать поиграть с упорядоченными заполнителями, такими как %1$s , %2$s . Кроме того, эти заполнители можно повторять без добавления дополнительных аргументов в код.
sprintf('<div class="container">
<p style="font-size:%1$spx;line-height:%1$spx;display:%4$s">
<span class="first-item" style="color:red">%2$s</span>
<span class="last-item" style="color:black">%3$s</span>
</p>
</div>', $size, $text1, $text2, $display);
Сравнение производительности
Начальная конфигурация нашего теста:
- PHP 7.3
- Количество итераций — 5 000 000
- Простой случай — Тук-тук, у $lang есть ты
- Сложный — это Knock Knock, у вас есть «$ lang». Проснись $name, $action
Полученные результаты:
ОДИНАРНАЯ КАВЫЧКА | ДВОЙНЫЕ КАВЫЧКИ | СПРИНТ | СПРИНТФ (ALT) | HEREDOC | |
---|---|---|---|---|---|
простой случай, мс | 275 | 259 | 533 | 572 | 260 |
сложный случай, мс | 685 | 479 | 935 | 888 | 487 |
МИФ: Использование « быстрее, чем ». PHP не будет использовать дополнительную обработку для интерпретации содержимого одинарных кавычек, тогда как с двойными кавычками PHP должен анализировать и проверять, есть ли какие-либо переменные.
В настоящее время аргумент о том, что один из этих вариантов лучше другого, трудно защитить, если вы не начнете объединять строки с переменными, и в этом случае метод двойных кавычек определенно выигрывает.
Резюме
Мы считаем вариант с переменной внутри строки наиболее удобным способом объединения строк и переменных. Однако обычно рекомендуется использовать каждый из этих методов для различных сценариев.