Solved

PHP HEREDOC parsing process?

Posted on 2014-10-02
13
184 Views
Last Modified: 2014-10-03
Hello guys, I have a question of PHP HEREDOC parsin process.

I am trying to implement HEREDOC as a templating engine, where I would have a programmatic output of pages, so no "naked" code inside.

The principle is simple - I have a series of strings with parts, or entire HEREDOC HTML pages, that are called with function that render the entire page.

This simple trick is utilized to process functions inside HEREDOC (as heredoc is parsed):
function fn($data) {
  return $data;
}
$fn = 'fn';

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

Open in new window



THE PROBLEM FOLLOWS:

Calling simple stuff from inside HEREDOC is fine, say PHP time, or a string or two. But if I call functions I made, for example those that pull stuff from a database, the function output is rendered first.

WTF I thought, and tested two PHP / Apache combos on two platforms and the behavior is the same.

Say I have:

<<<HEREDOC
1
2
3(function)
4(function)
5
HEREDOC;

What it will be outputted is:

3(function) - result
4(function) - result
1
2
5

**************************

Is there any way I could prevent this, or a workaround, or whatever?

The reason why I ask is that I would like to have clean and reusable snippets of HTML code inside PHP, without nasty includes and breaking out and into the code.


THANKS!! (I know this one is hard.)
0
Comment
Question by:mrmut
  • 4
  • 4
  • 3
  • +1
13 Comments
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40358139
You need to show us a simple example that does what you're talking about.  Although I don't think I would ever put the functions inside the HEREDOC myself.  I would always assign the function result to a simple variable before the HEREDOC and then use the variable inside it.
0
 

Author Comment

by:mrmut
ID: 40358152
I tried to put stuff inside variable before heredoc, but the result was the same. It was outputted before any other heredoc content.

Here is the sample (I will not be able to answer more jsut now, as I will go to sleep now, have to rise up early in the morning).


      
echo <<<HEREDOC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
{$heredoc(splice_html_title($title))}
</head>
<body>
{$heredoc(splicemaster_return_message())}
{$heredoc(splice_quick_add_article_form())}
{$heredoc(list_articles("archive"))}
{$heredoc(display_all_articles_in_a_html_table())}
</body>
</html>
HEREDOC;
	}

Open in new window



First string calls local title.
Next two call static heredoc html elsewhere.
The final two call functions that build formatted HTML out of the database.

The final two functions are outputted first, before entire HEREDOC, everythng else follows )which is kind of crap, making the function more or less useless for the purpose).
0
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40358174
I don't see how that works at all to do anything.  Too much missing to try to help you.
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
ID: 40358214
In your custom functions are you using echo to output the results or return?

If you are using echo you will get the results you have seen for obvious reasons - you would need to use a return.

This simple code seems to work - if I understand your question it is what you are wanting?
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="http://code.jquery.com/jquery.js"></script>
</head>
<body>
<?php
function myTestFunction($d)
{
	return "The square of {$d} is " . ($d * $d);
}
function heredoc($d) 
{
	return $d;
}
$heredoc = 'heredoc';
echo <<< HEREDOC
This is a test to see if this
{$heredoc(myTestFunction(2))}
Is called at the right point
HEREDOC;
?>
</body>
</html>

Open in new window

Outputs
This is a test to see if this The square of 2 is 4 Is called at the right point 

Open in new window

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40358226
Here is an example showing how to use HEREDOC.  Please post back if you still have questions, ~Ray

<?php // demo/html5_template.php
error_reporting(E_ALL);


// SEE: http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28530287.html
// REF: http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc


// CREATE VARIABLES FOR OUR HTML
$dat = date('r');
$xyz = "Hello @mrmut, this page was rendered at $dat";


// CREATE OUR WEB PAGE IN HTML5 FORMAT, USING THE PRE-DEFINED VARIABLES
$htm = <<<EOD
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>HTML5 Page Created with HEREDOC Notation</title>
</head>
<body>

<noscript>Your browsing experience will be much better with JavaScript enabled!</noscript>

<p>$xyz</p>

</body>
</html>
EOD;


// RENDER THE WEB PAGE
echo $htm;

Open in new window


Executive summary: Make it easier on yourself by creating all of the variables first, then use the HEREDOC string as a template; don't try to embed data logic in the "view" portion of the application.
0
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40358259
On this page http://us1.php.net/manual/en/language.types.string.php , it says...
Using single curly braces ({}) will not work for accessing the return values of functions or methods or the values of class constants or static class variables.

I got variables and variables returned from functions to work in this simple demo... but I can't get a function to return anything in a HEREDOC no matter what punctuation I put around it.
<?php 
error_reporting(E_ALL);
ini_set('display_errors','1');
 ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>HEREDOC Test</title>
</head>
<body>
<h1>HEREDOC Test</h1>
<?php 
$str1 = "This is string one.";
$str2 = "And this is string 2.";
$here1 = <<<HEREDOC
In this document: $str1 $str2
HEREDOC;

echo $here1;
echo "<br>";

function tfirst() {
	return "This is string one.";
	}
function tsec() {
	return "And this is string 2.";
	}

$fnc1 = tfirst();
$fnc2 = tsec();

$here2 = <<<HEREDOC
In this document: $fnc1 $fnc2
HEREDOC;

echo $here2;
echo "<br>";

$here3 = <<<HEREDOC
In this document: {tfirst()} {tsec()}
HEREDOC;

echo $here3; // this one fails.
echo "<br>";

 ?>
</body>
</html>

Open in new window

0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40358267
echo $here3; // this one fails.
As well it should.  Embedding logic in a display layer violates all kinds of design patterns.  It's one of those things like multiple inheritance.  Experienced programmers know better!
0
 
LVL 82

Expert Comment

by:Dave Baldwin
ID: 40358288
It was part of a simple demonstration of what did and did not work.  And the PHP man page says it won't work either.  I put that together because the OP didn't give an example that we could test.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40358426
Yep, good call Dave.
0
 

Author Comment

by:mrmut
ID: 40358736
Thanks all! This is overwhelming! Have to read all and test, than I will get back and reply!
0
 

Author Closing Comment

by:mrmut
ID: 40359602
Thank you, echoing was the issue, return works as it should.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40359653
You are welcome - thanks for the points.
0
 

Author Comment

by:mrmut
ID: 40359664
No problems, I am grateful to you. I have also posted this as Stack Overflow with no good answers (apart from the usual: "why I am doing something at all") and have banged my head a LOT about this.

I know that using HEREDOC is not usual modus operandi with these things, but I like the idea of programmatic snippets that I can call from withing the program itself.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to count occurrences of each item in an array.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now