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

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

в PHP 5, это is возможно фактически выполнять вызовы функций в {} фигурных скобках внутри строки 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. Не то чтобы это плохо, но это объясняет мою инерция.. Я за то, чтобы выяснить, как сделать жизнь проще, хотя, поэтому я смотрю в шаблоны сейчас.

16 ответов


Я бы вообще не использовал HEREDOC для этого, лично. Это просто не делает для хорошей системы "построения шаблонов". Весь ваш HTML заблокирован в строке, которая имеет несколько недостатков

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

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

template_file.в PHP

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

.в PHP

<?php

$page_title = "This is a simple demo";

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

include('template_file.php');

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

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

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

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

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

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


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

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


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

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

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

Шаблон Файл:

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

сценарий:

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

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

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

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


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

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

этот фрагмент определит переменные с именем ваших определенных функций в 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;

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


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


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

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


найдено хорошее решение с функцией упаковки здесь: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)}";

немного поздно, но все же. Это возможно в heredoc!

посмотрите в руководстве php, раздел "сложный (фигурный) синтаксис"


вот хороший пример использования предложения @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, добавляя суффикс после каждого имени Поля. Это типичная задача на стороне сервера.


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

$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


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

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

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


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

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

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