Вызов функций PHP в строках HEREDOC

В PHP строковые объявления HEREDOC действительно полезны для вывода блока html. Вы можете анализировать переменные, просто ставя перед ними префикс $, но для более сложного синтаксиса (например, $ var [2] [3]) вы должны поместить свое выражение в фигурные скобки {}.

В PHP 5 этоis можно на самом деле делать вызовы функций в фигурных скобках {} внутри строки HEREDOC, но вам придется проделать небольшую работу. Само имя функции должно храниться в переменной, и вы должны вызывать его, как если бы это была функция с динамическим именем. Например:

<code>$fn = 'testfunction';
function testfunction() { return 'ok'; }
$string = <<< heredoc
plain text and now a function: {$fn()}
heredoc;
</code>

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

<code>$string = <<< heredoc
plain text and now a function: {testfunction()}
heredoc;
</code>

Есть и другие способы, кроме первого примера кода, такие как выход из HEREDOC для вызова функции или решение проблемы и выполнение чего-то вроде:

<code>?>
<!-- directly output html and only breaking into php for the function -->
plain text and now a function: <?PHP print testfunction(); ?>
</code>

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

Итак, суть моего вопроса такова: есть ли более элегантный подход к этому?

Edit based on responses: Конечно, кажется, что какой-то движок шаблонов сделает мою жизнь намного проще, но это потребует от меня инверсии моего обычного стиля PHP. Не то, чтобы это было плохо, но это объясняет мою инерцию. Хотя я и собираюсь найти способы облегчить жизнь, поэтому сейчас я ищу шаблоны.

 rinogo06 мар. 2018 г., 01:21
Это не совсем ответ на ваш вопрос, но, учитывая слабую поддержку вызовов функций в операторах heredoc, я обычно просто генерирую нужные мне строки перед печатью heredoc. Тогда я могу просто использовать что-то вродеText {$string1} Text {$string2} Text в наследстве.

Ответы на вопрос(16)

либо создайте в случае необходимости):

<?php
  class Fn {
    public function __call($name, $args) {
      if (function_exists($name)) {
        return call_user_func_array($name, $args);
      }
    }
  }

  $fn = new Fn();
?>

Теперь любой вызов функции проходит через$fn экземпляр. Так что существующая функцияtestfunction() может быть вызван в heredoc с{$fn->testfunction()}

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

 Matthew Lock15 февр. 2013 г., 10:00
+ 1 для {$ fn-> testfunction ()}
 Brandon03 февр. 2011 г., 20:40
Это хорошее решение для тех случаев, когда нельзя просто добавить шаблонизатор в существующий проект. Спасибо, сейчас пользуюсь.
 Markus18 окт. 2011 г., 18:43
не следует широко использовать, когда производительность критична: я читал, что производительность в несколько раз хуже дляcall_user_func_array, последний раз в комментариях на php.net: Php.net / ручной / EN / function.call-пользователем функ-array.php # 97473
 MikeSchinkel04 сент. 2012 г., 22:37
Ницца! Я люблю это, почему я не думал об этом?!? : -)

Для полноты вы также можете использовать!${''} черная маги parser hack:

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;
 CJ Dennis25 февр. 2018 г., 11:54
А если хочешь напечататьNAN также используйте"${(${''} = date('Y-m-d H:i:s', strtotime('-1 month')) )==NAN}".
 CJ Dennis25 февр. 2018 г., 11:22
Это работает, потому чтоfalse == ''. Определите переменную с именем длины 0 ''). Установите желаемое значение ${''} = date('Y-m-d H:i:s', strtotime('-1 month'))). Отрицать это !) и преобразовать его в переменную ${false}).false нужно преобразовать в строку, а(string)false === ''. Если вы попытаетесь напечатать ложное значение, вместо этого произойдет ошибка. Следующая строка работает как с истинными, так и с ложными значениями, за счет того, что она еще более нечитаема:"${(${''}=date('Y-m-d H:i:s', strtotime('-1 month')))!=${''}}".
 Starx26 янв. 2017 г., 11:39
Ты ходил в Хогвартс?

http: //blog.nazdrave.net/ р = 626

function heredoc($param) {
    // just return whatever has been passed to us
    return $param;
}

$heredoc = 'heredoc';

$string = <<<HEREDOC
\$heredoc is now a generic function that can be used in all sorts of ways:
Output the result of a function: {$heredoc(date('r'))}
Output the value of a constant: {$heredoc(__FILE__)}
Static methods work just as well: {$heredoc(MyClass::getSomething())}
2 + 2 equals {$heredoc(2+2)}
HEREDOC;

// The same works not only with HEREDOC strings,
// but with double-quoted strings as well:
$string = "{$heredoc(2+2)}";
 CJ Dennis24 февр. 2018 г., 04:01
Я предложил точно такое же решение за 2,5 года до этого. Stackoverflow.com / а / 10713298/1166898

но это немного проще, чем использовать класс, который вы можете использовать:

function fn($data) {
  return $data;
}
$fn = 'fn';

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;
 Paulo Buchsbaum18 янв. 2013 г., 05:12
Отличный @CJDennis! Это лучшее и самое чистое решение для использования вызова функций внутри HEREDOC. В некоторых ситуациях есть хороший ресурс. На моем сайте я использую HEREDOC для генерации форм с 22 строками полей (блок HEREDOC внутри цикла FOR) с вызовом функции для генерации позиции tabindex.
 CJ Dennis29 нояб. 2013 г., 05:33
Ты даже можешь сделать это:$my_string = "Half the number of seconds since the Unix Epoch: {$fn(time() / 2 . ' Yes! Really!')}";
 My125 дек. 2016 г., 23:42
о, годегольф? хорошо, впусти меня:$fn=function($data){return $data;}; Это должно быть самое короткое время
 CJ Dennis20 сент. 2016 г., 04:31
@ devsmt Ты прав. И еще короче это:$fn = function ($data) { return $data; };
 devsmt19 сент. 2016 г., 15:16
более компактное определение:$fn = function fn($data) { return $data; };

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

function add ($int) { return $int + 1; }
$f=get_defined_functions();foreach($f[user]as$v){$v=$v;}

$string = <<< heredoc
plain text and now a function: {$add(1)}
heredoc;

Теперь буду работать.

Я бы сделал следующее:

$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());

Не уверен, что считаешь это более элегантным ...

 Doug Kavendek13 апр. 2011 г., 18:09
Я уже использую этот синтаксис в первом примере; у него есть недостаток - помещать имя функции в переменную, прежде чем вы сможете вызывать его внутри фигурных скобок в разделе heredoc, чего я и пытался избежать.

Вы забываете о лямбда-функции:

$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
    The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;

Вы также можете использовать функцию create_function

но случайно наткнулся на это. Для будущих читателей вот что я, вероятно, сдела

Я бы просто использовал выходной буфер. Таким образом, по сути, вы начинаете буферизацию с использованием ob_start (), затем включаете свой «файл шаблона» с любыми функциями, переменными и т. Д. Внутри него, получаете содержимое буфера и записываете его в строку, а затем закрываете буфер. Затем вы использовали любые переменные, которые вам нужны, вы можете запустить любую функцию, и у вас все еще есть подсветка синтаксиса HTML, доступная в вашей IDE.

Вот что я имею в виду:

Шаблон файла:

<?php echo "plain text and now a function: " . testfunction(); ?>

Script:

<?php
ob_start();
include "template_file.php";
$output_string = ob_get_contents();
ob_end_clean();
echo $output_string;
?>

Так что скрипт включает template_file.php в свой буфер, выполняя любые функции / методы и назначая любые переменные по пути. Затем вы просто записываете содержимое буфера в переменную и делаете с ней все, что хотите.

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

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

 Jay Smoke16 нояб. 2017 г., 15:49
спасибо, спасибо, спасибоuuuuuuuu

что использование heredoc отлично подходит для генерации HTML-кода. Например, я нахожу следующее почти полностью нечитаемым.

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

Однако, чтобы достичь простоты, вы должны оценить функции перед началом работы. Я не верю, что это такое ужасное ограничение, поскольку при этом вы в конечном итоге отделяете свои вычисления от отображения, что обычно является хорошей идеей.

, что следующее вполне читабельно:

$page_content = getPageContent();

print <<<END
<html>
<head>
  <title>$page_title</title>
</head>
<body>
$page_content
</body>
END;

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

 Leven11 дек. 2012 г., 14:29
Самый простой, самый читаемый ответ.
 Josh from Qaribou14 сент. 2015 г., 20:20
Последние 4 года оказались намного умнее, чем большинство других подходов. Использование композиции в ваших шаблонах (создание большой страницы, состоящей из меньших страниц) и разделение всей логики управления - это стандартный подход для всех, кто серьезно относится к шаблонам: ReactJS от Facebook отлично подходит для этого (как и XHP), как и XSLT (который Я не люблю, но академически здоров) Единственные стилистические примечания, которые я хотел бы сделать: я всегда использую {} вокруг своих переменных, в основном для последовательности в удобочитаемости и чтобы избежать несчастных случаев позже. Кроме того, не забудьте htmlspecialchars () любые данные, поступающие от пользователей.
Решение Вопроса

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

Нет варианта для WYSIWYG Нет завершения кода для HTML из IDE Выход (HTML) заблокирован для логических файлов В конечном итоге вам придется использовать такие хаки, как то, что вы пытаетесь сделать сейчас, для достижения более сложных шаблонов, таких как зацикливание

Получите базовый шаблонизатор или просто используйте PHP с включениями - вот почему у языка есть<?php а также?> разделители.

Template_file.php

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

Index.php

<?php

$page_title = "This is a simple demo";

function getPageContent() {
    return '<p>Hello World!</p>';
}

include('template_file.php');
 Jimbo14 мар. 2013 г., 10:57
Short приятнее, чище и его легче читать. В ваших взглядах<?=$title?> является Много лучше, чем <? php echo $ title; ?>. Недостатком является то, что для распространения у многих ini-ов есть короткие теги.Н, Угадай, что?? По состоянию наPHP 5.4, короткие теги включены в PHP независимо от настроек ini! Поэтому, если вы программируете с требованием 5.4+ (скажем, вы используете черты, например), используйте эти потрясающие короткие теги !!
 callmetwan16 мая 2014 г., 18:15
Кстати, <? = $ Blah?> По умолчанию включено в 5.4, даже если короткие теги отключены.
 MikeSchinkel09 сент. 2012 г., 23:32
Нет, я не говорю, что мне стыдно набирать 7 символов; Вы неправильно приписываете мои проблемы. Это не Набрав Я обеспокоен тем, что это Чтение. Эти символы создают много визуального шума, который значительно усложняет сканирование исходного кода и понимание того, что делает код. Для меня по крайней мере это МНОГО легче читать HEREDOC. (И кстати, это 7-символьное время, сколько раз оно используется в данном фрагменте HTML. Но я отступаю.)
 Peter Bailey05 сент. 2012 г., 21:26
Есть сокращение для эха:<?=$valueToEcho;?> или<%=$valueToEcho;%> зависит от ваших настроек INI.
 MikeSchinkel05 сент. 2012 г., 23:27
Почти все, что я читал об использовании этих коротких слов, говорит, что их использование - плохая практика, и я согласен. Так, к сожалению, если вы пишете код для распространения не может зависеть от этих параметров INI таким образом делая «поддержку» РНР для них тоо для распределенного кода. Кстати, мне приходилось исправлять ошибки в плагинах WordPress других людей не раз, потому что они использовали эти сокращения.
<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

Smarty как движок шаблонов - я сам не пробовал других, но он мне помог.

Если ты хочешь придерживаться своего нынешнего подхода @ Sa шаблоны, что плохого в буферизации вывода? Это даст вам гораздо больше гибкости, чем объявление переменных, которые являются строковыми именами функций, которые вы хотите вызывать.

function double($i)
{ return $i*2; }

function triple($i)
{ return $i*3;}

$tab = 'double';
echo "{$tab(5)} is $tab 5<br>";

$ta,b = 'triple';
echo "{$tab(5)} is $tab 5<br>";

Например, для синтаксиса HEREDOC целесообразно создавать огромные формы с отношениями мастер-деталь в базе данных. Можно использовать функцию HEREDOC внутри элемента управления FOR, добавляя суффикс после каждого имени поля. Это типичная задача на стороне сервера.

что он также работает со строками в двойных кавычках.

http: //www.php.net/manual/en/language.types.string.ph

Интересный совет в любом случае.

<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>

Ваш ответ на вопрос