Search code examples
phpstringheredoc

Calling PHP functions within HEREDOC strings


In PHP, the HEREDOC string declarations are really useful for outputting a block of html. You can have it parse in variables just by prefixing them with $, but for more complicated syntax (like $var[2][3]), you have to put your expression inside {} braces.

In PHP 5, it is possible to actually make function calls within {} braces inside a HEREDOC string, but you have to go through a bit of work. The function name itself has to be stored in a variable, and you have to call it like it is a dynamically-named function. For example:

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

As you can see, this is a bit more messy than just:

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

There are other ways besides the first code example, such as breaking out of the HEREDOC to call the function, or reversing the issue and doing something like:

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

The latter has the disadvantage that the output is directly put into the output stream (unless I'm using output buffering), which might not be what I want.

So, the essence of my question is: is there a more elegant way to approach this?

Edit based on responses: It certainly does seem like some kind of template engine would make my life much easier, but it would require me basically invert my usual PHP style. Not that that's a bad thing, but it explains my inertia.. I'm up for figuring out ways to make life easier though, so I'm looking into templates now.


Solution

  • I would not use HEREDOC at all for this, personally. It just doesn't make for a good "template building" system. All your HTML is locked down in a string which has several disadvantages

    • No option for WYSIWYG
    • No code completion for HTML from IDEs
    • Output (HTML) locked to logic files
    • You end up having to use hacks like what you're trying to do now to achieve more complex templating, such as looping

    Get a basic template engine, or just use PHP with includes - it's why the language has the <?php and ?> delimiters.

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