Advantages/Inconveniences of Heredoc VS Nowdoc in PHP

Advantages / inconveniences of heredoc vs nowdoc in php

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping.

http://php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc

In other words:

$foo = 'bar';

$here = <<<HERE
I'm here, $foo !
HERE;

$now = <<<'NOW'
I'm now, $foo !
NOW;

$here is "I'm here, bar !", while $now is "I'm now, $foo !".

If you don't need variable interpolation but need special characters like $ inside your string, Nowdocs are easier to use. That's all.

What is the pro and cons using Heredoc Notation in your PHP?

99% of the time I use it, it's for SQL queries eg:

$sql = <<<END
SELECT *
FROM sometable
WHERE value > 100
ORDER BY name
END;

I find it easier to spot such queries in the source code and copy and paste them into something to run them. Your mileage may vary. Note: you can do multi-line with normal strings. I tend to avoid this however as the first line is indented differently to the rest.

The biggest "pro" as far as I'm concerned is that you don't need to escape quotes. That's particularly an issue with markup. Decide for yourself which is easier to read. Assuming:

$name = 'foo';
$type = 'text';
$value = 'Default value';

Version 1: single quotes

$html = '<input type="' . $type . ' name="' . $name . '" value="' . $value . '">';

Version 2: double quotes

$html = "<input type=\"$type\" name=\"$name\" value=\"$value\">";

Version 3: heredoc

$html = <<<END
<input type="$type" name="$name" value="$value">
END;

Note: in version 2 you can of course use single quotes for attribute values to solve the escaping problem but the point is you have to worry about things like this. Personally I don't like to mix attribute quote types in markup either.

Interpreting variables but ignoring escape sequences in PHP HEREDOC

At the risk of misunderstanding the intended output, I think you could just escape the backslashes. (I'm assuming you want the single backslashes included in the output.)

$title = "My title here";
$date = "Aug 12, 2017";

$latex_code = <<<LCODE
\\documentclass{article}

\\usepackage{graphicx}

\\pagestyle{head}
\\firstpageheader{
$title
$date
}
LCODE;

Obviously if you don't do that, some of them (e.g. \f) will be escape sequences that will be interpreted.

escaping ?php and ? when outputing to a file - nowdoc/heredoc

If you're intentionally using NOWDOC syntax, make sure your PHP server is running 5.3 or later, since that was when it was introduced. (You can check using phpinfo();). That would explain why it worked on your dev server but not on production.

nowdoc inside a function

As mentioned in my comment, if you want to keep your formatting on both pages, just use include():

/string.php

<?php
$str = <<<'EOD'
This is a string
EOD;
// This line after "EOD;" needs something on it or it may throw this error:
// Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN)

/myfunction.php

<?php
function myfunction()
{
# Include the nowdoc file
include(__DIR__.'/string.php');
# Return the string back
return $str;
}

What is the advantage of using heredoc in PHP?

The heredoc syntax is much cleaner to me and it is really useful for multi-line strings and avoiding quoting issues. Back in the day I used to use them to construct SQL queries:

$sql = <<<SQL
select *
from $tablename
where id in [$order_ids_list]
and product_name = "widgets"
SQL;

To me this has a lower probability of introducing a syntax error than using quotes:

$sql = "
select *
from $tablename
where id in [$order_ids_list]
and product_name = \"widgets\"
";

Another point is to avoid escaping double quotes in your string:

$x = "The point of the \"argument" was to illustrate the use of here documents";

The problem with the above is the syntax error (the missing escaped quote) I just introduced as opposed to here document syntax:

$x = <<<EOF
The point of the "argument" was to illustrate the use of here documents
EOF;

It is a bit of style, but I use the following as rules for single, double and here documents for defining strings:

  • Single quotes are used when the string is a constant like 'no variables here'
  • Double quotes when I can put the string on a single line and require variable interpolation or an embedded single quote "Today is ${user}'s birthday"
  • Here documents for multi-line strings that require formatting and variable interpolation.

Echo in heredoc / nowdoc syntax

I believe this is what you were intending to do, it's a bit awkard looking:

$fn = escape($mt->from_name);
$time = escape(date("F d, Y - h:i a", strtotime($mt->st_time)));
$stc = nl2br(escape($mt->st_content));

//START EMAIL
User::sendNewticket($send_to, 'Maintenance Ticket ' . Input::get('st_id'), <<<TEXT
Hello -<br><br>
TEXT
. Input::get('rec_message') . <<<TEXT2
<br><br>

<strong>Conversation:</strong><br><br>

$fn<br>
$time<br>
$stc<br>

TEXT2
);

The start of a heredoc must be the last thing on a line, so after that you drop down and immediately go into the text block. The end of the heredoc must be the only thing on the line, so to concatenate it you have to drop down a line before you can use the operator (.). You also don't need to use any quotation marks or append operators when inside a heredoc.

It's so unintuitive in fact, that even the StackOverflow Syntax highlighter gets it wrong, the first <<<TEXT works fine when I ran this:

$mt = new stdClass();
function escape($v){return $v;}
class User{static function sendNewTicket($a, $b, $c){echo $c;}}
class Input{static function get($a){return 'Got something';}}
$send_to = '';
$mt->from_name = 'Kitty';
$mt->st_time = '5th November';
$mt->st_content = <<<CONTENT
Dear Judy,

Lorem Dipsum and all that jazz.

Toodles,
Kitty.
CONTENT;

$fn = escape($mt->from_name);
$time = escape(date("F d, Y - h:i a", strtotime($mt->st_time)));
$stc = nl2br(escape($mt->st_content));

//START EMAIL
User::sendNewticket($send_to, 'Maintenance Ticket ' . Input::get('st_id'), <<<TEXT
Hello -<br><br>
TEXT
. Input::get('rec_message') . <<<TEXT2
<br><br>

<strong>Conversation:</strong><br><br>

$fn<br>
$time<br>
$stc<br>

TEXT2
);

It produced:

Hello -<br><br>Got something<br><br>

<strong>Conversation:</strong><br><br>

Kitty<br>
November 05, 2014 - 12:00 am<br>
Dear Judy,<br />
<br />
Lorem Dipsum and all that jazz.<br />
<br />
Toodles,<br />
Kitty.<br>

Though I'm sure it'll look better with your data.

Edit: And as Blizz very correctly points out below, if you save the rec_message into a variable, you can avoid the concatenation altogether:

$recMessage = Input::get('rec_message');
User::sendNewticket($send_to, 'Maintenance Ticket ' . Input::get('st_id'), <<<TEXT
Hello -<br><br>
$recMessage
<br><br>

<strong>Conversation:</strong><br><br>

$fn<br>
$time<br>
$stc<br>

TEXT
);

Edit 2: With the extra messages, you should use something like this to simplify the email:

$messages = '';
foreach($st_messages->results() as $mt)
{

$fn = escape($mt->from_name);
$time = escape(date("F d, Y - h:i a", strtotime($mt->st_time)));
$stc = nl2br(escape($mt->st_content));

$messages .= <<<MESSAGE

$fn<br>
$time<br>
$stc<br><br>

MESSAGE;
}

$recMessage = Input::get('rec_message');
User::sendNewticket($send_to, 'Maintenance Ticket ' . Input::get('st_id'), <<<TEXT
Hello -<br><br>
$recMessage
<strong>Conversation:</strong><br><br>

$messages

Thanks,<br>
Support Team

TEXT
);
?>

Which with some basic dummy text produces:

Hello -<br><br>
Got something
<strong>Conversation:</strong><br><br>

Person<br>
November 11, 2014 - 12:00 am<br>
My message blah blah<br><br>

sdfasdf<br>
April 11, 2014 - 12:00 am<br>
My message asdfasdf blah blah<br><br>

Thanks,<br>
Support Team

Heredoc in Laravel database seed

Instead of using heredoc, you can instead use nowdoc. From the documentation:

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc.

See also this answer by deceze which gives a practical example of the difference between the two:

$foo = 'bar';

$here = <<<HERE
I'm here, $foo!
HERE;

$now = <<<'NOW'
I'm now, $foo!
NOW;

$here is "I'm here, bar!", while $now is "I'm now, $foo!".

Calling PHP functions within HEREDOC strings

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


Related Topics



Leave a reply



Submit