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

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

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

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

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

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

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

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

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

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

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

Ответ 1

Я бы не использовал HEREDOC для этого лично. Это просто не делает для хорошей системы создания шаблонов. Весь ваш 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');

Ответ 2

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

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

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;

Ответ 3

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

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

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

Ответ 4

Попробуйте это (либо как глобальную переменную, либо создайте ее, когда вам это нужно):

<?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 для сопоставления метода класса с фактической функцией, которая должна быть вызвана.

Ответ 5

Я немного опоздал, но я случайно наткнулся на него. Для будущих читателей, вот что я бы сделал:

Я бы просто использовал выходной буфер. Таким образом, вы начинаете буферизацию с помощью 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;
?>

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

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

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

Ответ 6

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

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;

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

Ответ 7

Я думаю, что использование 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.

Ответ 8

Я бы посмотрел на Smarty в качестве механизма шаблона - я сам не пробовал никаких других, но это сделал мне хорошо.

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

Ответ 9

найдено приятное решение с функцией обертывания здесь: http://blog.nazdrave.net/?p=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)}";

Ответ 10

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

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;

Ответ 11

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

Ответ 13

Вот хороший пример с использованием предложения @CJDennis:

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

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

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

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

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

Ответ 14

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

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

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

Ответ 15

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

Ответ 16

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

$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

Ответ 17

<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

вы должны попробовать. после окончания ETO; команде вы должны ввести ввод.