How to write a loop while inside heredoc [duplicate] - php

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.

If you really want to do this but a bit simpler than using a class you can use:
function fn($data) {
return $data;
}
$fn = 'fn';
$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;

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

I would do the following:
$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());
Not sure if you'd consider this to be more elegant ...

For completeness, you can also use the !${''} black magic parser hack:
echo <<<EOT
One month ago was { ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))} }.
EOT;
See it live on 3v4l.org.
Note: PHP 8.2 deprecated bare ${} variable variables within strings, in preference to the explicit { ${} } syntax. The example above uses this explicit format to remove the deprecation notice, though it makes this method even more noisy!

Try this (either as a global variable, or instantiated when you need it):
<?php
class Fn {
public function __call($name, $args) {
if (function_exists($name)) {
return call_user_func_array($name, $args);
}
}
}
$fn = new Fn();
?>
Now any function call goes through the $fn instance. So the existing function testfunction() can be called in a heredoc with {$fn->testfunction()}
Basically we are wrapping all functions into a class instance, and using PHP's __call magic method to map the class method to the actual function needing to be called.

I'm a bit late, but I randomly came across it. For any future readers, here's what I would probably do:
I would just use an output buffer. So basically, you start the buffering using ob_start(), then include your "template file" with any functions, variables, etc. inside of it, get the contents of the buffer and write them to a string, and then close the buffer. Then you've used any variables you need, you can run any function, and you still have the HTML syntax highlighting available in your IDE.
Here's what I mean:
Template File:
<?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;
?>
So the script includes the template_file.php into its buffer, running any functions/methods and assigning any variables along the way. Then you simply record the buffer's contents into a variable and do what you want with it.
That way if you don't want to echo it onto the page right at that second, you don't have to. You can loop and keep adding to the string before outputting it.
I think that's the best way to go if you don't want to use a templating engine.

found nice solution with wrapping function here: 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)}";

This snippet will define variables with the name of your defined functions within userscope and bind them to a string which contains the same name. Let me demonstrate.
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;
Will now work.

I think using heredoc is great for generating HTML code. For example, I find the following almost completely unreadable.
<html>
<head>
<title><?php echo $page_title; ?></title>
</head>
<body>
<?php echo getPageContent(); ?>
</body>
However, in order to achieve the simplicity you are forced to evaluate the functions before you start. I don't believe that is such a terrible constraint, since in so doing, you end up separating your computation from display, which is usually a good idea.
I think the following is quite readable:
$page_content = getPageContent();
print <<<END
<html>
<head>
<title>$page_title</title>
</head>
<body>
$page_content
</body>
END;
Unfortunately, even though it was a good suggestion you made in your question to bind the function to a variable, in the end, it adds a level of complexity to the code, which is not worth, and makes the code less readable, which is the major advantage of heredoc.

you are forgetting about lambda function:
$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;
You also could use the function create_function

This is a little more elegant today on php 7.x
<?php
$test = function(){
return 'it works!';
};
echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;

I'd take a look at Smarty as a template engine - I haven't tried any other ones myself, but it has done me well.
If you wanted to stick with your current approach sans templates, what's so bad about output buffering? It'll give you much more flexibility than having to declare variables which are the string names of the functions you want to call.

A bit late but still.
This is possible in heredoc!
Have a look in the php manual, section "Complex (curly) syntax"

Here a nice example using #CJDennis proposal:
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>";
For instance, a good use for HEREDOC syntax is generate huge forms with master-detail relationship in a Database. One can use HEREDOC feature inside a FOR control, adding a suffix after each field name. It's a typical server side task.

Guys should note that it also works with double-quoted strings.
http://www.php.net/manual/en/language.types.string.php
Interesting tip anyway.

<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;
you should try it . after end the ETO; command you should give an enter.

Related

PHP implode in Heredoc [duplicate]

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.
If you really want to do this but a bit simpler than using a class you can use:
function fn($data) {
return $data;
}
$fn = 'fn';
$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;
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');
I would do the following:
$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());
Not sure if you'd consider this to be more elegant ...
For completeness, you can also use the !${''} black magic parser hack:
echo <<<EOT
One month ago was { ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))} }.
EOT;
See it live on 3v4l.org.
Note: PHP 8.2 deprecated bare ${} variable variables within strings, in preference to the explicit { ${} } syntax. The example above uses this explicit format to remove the deprecation notice, though it makes this method even more noisy!
Try this (either as a global variable, or instantiated when you need it):
<?php
class Fn {
public function __call($name, $args) {
if (function_exists($name)) {
return call_user_func_array($name, $args);
}
}
}
$fn = new Fn();
?>
Now any function call goes through the $fn instance. So the existing function testfunction() can be called in a heredoc with {$fn->testfunction()}
Basically we are wrapping all functions into a class instance, and using PHP's __call magic method to map the class method to the actual function needing to be called.
I'm a bit late, but I randomly came across it. For any future readers, here's what I would probably do:
I would just use an output buffer. So basically, you start the buffering using ob_start(), then include your "template file" with any functions, variables, etc. inside of it, get the contents of the buffer and write them to a string, and then close the buffer. Then you've used any variables you need, you can run any function, and you still have the HTML syntax highlighting available in your IDE.
Here's what I mean:
Template File:
<?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;
?>
So the script includes the template_file.php into its buffer, running any functions/methods and assigning any variables along the way. Then you simply record the buffer's contents into a variable and do what you want with it.
That way if you don't want to echo it onto the page right at that second, you don't have to. You can loop and keep adding to the string before outputting it.
I think that's the best way to go if you don't want to use a templating engine.
found nice solution with wrapping function here: 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)}";
This snippet will define variables with the name of your defined functions within userscope and bind them to a string which contains the same name. Let me demonstrate.
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;
Will now work.
I think using heredoc is great for generating HTML code. For example, I find the following almost completely unreadable.
<html>
<head>
<title><?php echo $page_title; ?></title>
</head>
<body>
<?php echo getPageContent(); ?>
</body>
However, in order to achieve the simplicity you are forced to evaluate the functions before you start. I don't believe that is such a terrible constraint, since in so doing, you end up separating your computation from display, which is usually a good idea.
I think the following is quite readable:
$page_content = getPageContent();
print <<<END
<html>
<head>
<title>$page_title</title>
</head>
<body>
$page_content
</body>
END;
Unfortunately, even though it was a good suggestion you made in your question to bind the function to a variable, in the end, it adds a level of complexity to the code, which is not worth, and makes the code less readable, which is the major advantage of heredoc.
you are forgetting about lambda function:
$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;
You also could use the function create_function
This is a little more elegant today on php 7.x
<?php
$test = function(){
return 'it works!';
};
echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;
I'd take a look at Smarty as a template engine - I haven't tried any other ones myself, but it has done me well.
If you wanted to stick with your current approach sans templates, what's so bad about output buffering? It'll give you much more flexibility than having to declare variables which are the string names of the functions you want to call.
A bit late but still.
This is possible in heredoc!
Have a look in the php manual, section "Complex (curly) syntax"
Here a nice example using #CJDennis proposal:
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>";
For instance, a good use for HEREDOC syntax is generate huge forms with master-detail relationship in a Database. One can use HEREDOC feature inside a FOR control, adding a suffix after each field name. It's a typical server side task.
Guys should note that it also works with double-quoted strings.
http://www.php.net/manual/en/language.types.string.php
Interesting tip anyway.
<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;
you should try it . after end the ETO; command you should give an enter.

How to add or subtract in heredoc syntax? [duplicate]

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.
If you really want to do this but a bit simpler than using a class you can use:
function fn($data) {
return $data;
}
$fn = 'fn';
$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;
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');
I would do the following:
$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());
Not sure if you'd consider this to be more elegant ...
For completeness, you can also use the !${''} black magic parser hack:
echo <<<EOT
One month ago was { ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))} }.
EOT;
See it live on 3v4l.org.
Note: PHP 8.2 deprecated bare ${} variable variables within strings, in preference to the explicit { ${} } syntax. The example above uses this explicit format to remove the deprecation notice, though it makes this method even more noisy!
Try this (either as a global variable, or instantiated when you need it):
<?php
class Fn {
public function __call($name, $args) {
if (function_exists($name)) {
return call_user_func_array($name, $args);
}
}
}
$fn = new Fn();
?>
Now any function call goes through the $fn instance. So the existing function testfunction() can be called in a heredoc with {$fn->testfunction()}
Basically we are wrapping all functions into a class instance, and using PHP's __call magic method to map the class method to the actual function needing to be called.
I'm a bit late, but I randomly came across it. For any future readers, here's what I would probably do:
I would just use an output buffer. So basically, you start the buffering using ob_start(), then include your "template file" with any functions, variables, etc. inside of it, get the contents of the buffer and write them to a string, and then close the buffer. Then you've used any variables you need, you can run any function, and you still have the HTML syntax highlighting available in your IDE.
Here's what I mean:
Template File:
<?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;
?>
So the script includes the template_file.php into its buffer, running any functions/methods and assigning any variables along the way. Then you simply record the buffer's contents into a variable and do what you want with it.
That way if you don't want to echo it onto the page right at that second, you don't have to. You can loop and keep adding to the string before outputting it.
I think that's the best way to go if you don't want to use a templating engine.
found nice solution with wrapping function here: 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)}";
This snippet will define variables with the name of your defined functions within userscope and bind them to a string which contains the same name. Let me demonstrate.
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;
Will now work.
I think using heredoc is great for generating HTML code. For example, I find the following almost completely unreadable.
<html>
<head>
<title><?php echo $page_title; ?></title>
</head>
<body>
<?php echo getPageContent(); ?>
</body>
However, in order to achieve the simplicity you are forced to evaluate the functions before you start. I don't believe that is such a terrible constraint, since in so doing, you end up separating your computation from display, which is usually a good idea.
I think the following is quite readable:
$page_content = getPageContent();
print <<<END
<html>
<head>
<title>$page_title</title>
</head>
<body>
$page_content
</body>
END;
Unfortunately, even though it was a good suggestion you made in your question to bind the function to a variable, in the end, it adds a level of complexity to the code, which is not worth, and makes the code less readable, which is the major advantage of heredoc.
you are forgetting about lambda function:
$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;
You also could use the function create_function
This is a little more elegant today on php 7.x
<?php
$test = function(){
return 'it works!';
};
echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;
I'd take a look at Smarty as a template engine - I haven't tried any other ones myself, but it has done me well.
If you wanted to stick with your current approach sans templates, what's so bad about output buffering? It'll give you much more flexibility than having to declare variables which are the string names of the functions you want to call.
A bit late but still.
This is possible in heredoc!
Have a look in the php manual, section "Complex (curly) syntax"
Here a nice example using #CJDennis proposal:
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>";
For instance, a good use for HEREDOC syntax is generate huge forms with master-detail relationship in a Database. One can use HEREDOC feature inside a FOR control, adding a suffix after each field name. It's a typical server side task.
Guys should note that it also works with double-quoted strings.
http://www.php.net/manual/en/language.types.string.php
Interesting tip anyway.
<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;
you should try it . after end the ETO; command you should give an enter.

echo php code without commenting out php code

Let me rephrase this question. I'm trying to store the contents of an html file into a string. I would then like to have the php code in the html string convert the php to whatever the values I feed it later. I think the string interpolation might work. I might have over complicated it. But I think it would be interesting to still be able to use php tags for certain situations.
I would like to do something like this:
$str = 'some words';
$php = '<p><?= $str; ?></p>';
echo $php;
which would output to the DOM (source):
<p>some words</p>
or simply just on your browser screen
some words
What I get:
<p><!-- <?= $str; ?> --></p>
is this even possible?
I know the code above looks simple but this is just a simple case of the problem I am trying to solve.
<?php
// View
class View {
private static $paths = [];
private static function getTemplate($templatePath) {
if (!array_key_exists($templatePath, self::$paths)) {
// Filename must exist
if (!file_exists($templatePath)) {
die('File Doesn\'t Exist');
}
self::$paths[$templatePath] = file_get_contents($templatePath);
}
return self::$paths[$templatePath];
}
// Fill Template
public static function fill($vars, $templatePath) {
// Turn Vars into unique variables
extract($vars);
$input = self::getTemplate($templatePath);
// Get View Output
ob_start();
echo $input;
$output = ob_get_contents();
ob_end_clean();
return $output;
}
public static function fillWith($templatePath) {
}
}
Use string interpolation:
echo "<p>$str</p>";
Note the double-quoted syntax ("..."). Variables are not substituted in PHP if the string is single-quoted ('...').
As for your updated question
If you obtain the template string from external source, then PHP's string interpolation won't work (it would be a huge security risk if it would).
You may use regular expressions to replace occurrences of specific patterns.
Or use a template engine like Twig. It has more power than you need currently and requires some learning, but it's future-proof in case that you need more complex features sometime.
You may also make your template file a PHP script and include it (instead of file_get_contents). + Define the variables before the inclusion. Then PHP's usual string interpolation would work. But I do not recommend you to do it this way. It's not readable and introduces a potential security risk.
See also this question.
Thats so simple just use this:
<?php
$str = "some words";
echo "<p>$str</p>";
?>
Also some extra information about single and double quotes you finde here:
What is the difference between single-quoted and double-quoted strings in PHP?

Print <<< END; question

Okay, so I have a question. I use print <<< END followed by an END; after my html and variables instead of echo and print. I use this because it doesn't seem to have an effect on speed and the code just looks more organized in my opinion. I'm sure others will disagree but it's just my opinion.
I have a current project and that's the primary method I use to output HTML. No problems so far.
What are the disadvantages to using this? I have spoken with coders about it before, but they never really give me a reason not to use it just to not use it. I would appreciate any advice on this because I haven't had any problems with it.
The syntax you're describing is called a heredoc. As far as I know there is no performance difference between using heredocs and single- / double-quoted strings.
Heredocs can often help to prevent syntax errors, because there is no need to escape ' and " within the string. Another option would be to jump out of PHP into plain HTML, which requires no echo calls whatsoever:
<?php
... do things ...
?>
<div id="result"><?php var_dump($result); ?></div>
<?php
... do more things ...
?>
The only disadvantage i can think of is its harder to read for developers. This too is opinion but i find it much easier to read alternate syntax in template files, i.e.:
<?php if($something): ?>
<div id="something">
<?php echo $something->text ?>
</div>
<?php endif; ?>
And switching in and out like this is the only reason i can see to use heredoc as far as html is concerned. IF you have functions that are outputting massive amounts of html then you should change those to include a file in some manner. IE. you shoudl need to switch in and out of html except in your view, and those views should be separate completely form your functions or models. for exampl you should be doing:
function getSomething($var){
if($var){
$html = <<< HTML
<div id="something">
$var->text
</div>
HTML;
}
}
This is obvioulsy a simle example and actually this example isnt so bad, but if the HTML is more complex it starts to get jsut ugly. And in the case of methods on model classes its just plain evil no matter how simple the HTML is. Id prefer something like the following:
getSomething($var, $template = 'something.php')
{
if($var){
ob_start();
include($template); // $var is accessible in something.php
return ob_get_clean();
}
return null;
}
Of course the include will result in slight a performance hit but thats where caching comes in :-)

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.
If you really want to do this but a bit simpler than using a class you can use:
function fn($data) {
return $data;
}
$fn = 'fn';
$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;
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');
I would do the following:
$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());
Not sure if you'd consider this to be more elegant ...
For completeness, you can also use the !${''} black magic parser hack:
echo <<<EOT
One month ago was { ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))} }.
EOT;
See it live on 3v4l.org.
Note: PHP 8.2 deprecated bare ${} variable variables within strings, in preference to the explicit { ${} } syntax. The example above uses this explicit format to remove the deprecation notice, though it makes this method even more noisy!
Try this (either as a global variable, or instantiated when you need it):
<?php
class Fn {
public function __call($name, $args) {
if (function_exists($name)) {
return call_user_func_array($name, $args);
}
}
}
$fn = new Fn();
?>
Now any function call goes through the $fn instance. So the existing function testfunction() can be called in a heredoc with {$fn->testfunction()}
Basically we are wrapping all functions into a class instance, and using PHP's __call magic method to map the class method to the actual function needing to be called.
I'm a bit late, but I randomly came across it. For any future readers, here's what I would probably do:
I would just use an output buffer. So basically, you start the buffering using ob_start(), then include your "template file" with any functions, variables, etc. inside of it, get the contents of the buffer and write them to a string, and then close the buffer. Then you've used any variables you need, you can run any function, and you still have the HTML syntax highlighting available in your IDE.
Here's what I mean:
Template File:
<?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;
?>
So the script includes the template_file.php into its buffer, running any functions/methods and assigning any variables along the way. Then you simply record the buffer's contents into a variable and do what you want with it.
That way if you don't want to echo it onto the page right at that second, you don't have to. You can loop and keep adding to the string before outputting it.
I think that's the best way to go if you don't want to use a templating engine.
found nice solution with wrapping function here: 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)}";
This snippet will define variables with the name of your defined functions within userscope and bind them to a string which contains the same name. Let me demonstrate.
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;
Will now work.
I think using heredoc is great for generating HTML code. For example, I find the following almost completely unreadable.
<html>
<head>
<title><?php echo $page_title; ?></title>
</head>
<body>
<?php echo getPageContent(); ?>
</body>
However, in order to achieve the simplicity you are forced to evaluate the functions before you start. I don't believe that is such a terrible constraint, since in so doing, you end up separating your computation from display, which is usually a good idea.
I think the following is quite readable:
$page_content = getPageContent();
print <<<END
<html>
<head>
<title>$page_title</title>
</head>
<body>
$page_content
</body>
END;
Unfortunately, even though it was a good suggestion you made in your question to bind the function to a variable, in the end, it adds a level of complexity to the code, which is not worth, and makes the code less readable, which is the major advantage of heredoc.
you are forgetting about lambda function:
$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;
You also could use the function create_function
This is a little more elegant today on php 7.x
<?php
$test = function(){
return 'it works!';
};
echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;
I'd take a look at Smarty as a template engine - I haven't tried any other ones myself, but it has done me well.
If you wanted to stick with your current approach sans templates, what's so bad about output buffering? It'll give you much more flexibility than having to declare variables which are the string names of the functions you want to call.
A bit late but still.
This is possible in heredoc!
Have a look in the php manual, section "Complex (curly) syntax"
Here a nice example using #CJDennis proposal:
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>";
For instance, a good use for HEREDOC syntax is generate huge forms with master-detail relationship in a Database. One can use HEREDOC feature inside a FOR control, adding a suffix after each field name. It's a typical server side task.
Guys should note that it also works with double-quoted strings.
http://www.php.net/manual/en/language.types.string.php
Interesting tip anyway.
<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;
you should try it . after end the ETO; command you should give an enter.

Categories