When should I use echo with single vs double quotes?

I’m looking for quick rules of thumb for when to use echo with single quotes vs double quotes, including in special situations, like echoing JavaScript and large chunks of html.

Any variables within a string contained in double quotes will be evaluated before the string is displayed.

Variables within a string contained in single quotes are not evaluated before the string is displayed.

Just my opinion, but the best case to use double quotes is never. They don’t serve any real purpose and just make things unreadable. I always just use single quotes and concatenate all variables in.

For large of chunks of HTML I’d normally jump out of the PHP compiler, but if that’s somehow not an option I’d use heredoc.

Again, this is just my opinion, others might (nay, will) disagree :slight_smile:

agree 120% :slight_smile:

and if you’re using an IDE that colour codes your code, errors in strings with double quotes and containing variables are not as obvious because the whole string would be a single colour.

You can (well in at least some) in some software (I know at least Crimson Editor can) have it highlight variables a different colour from a string so that they stand out.

As said - use heredoc - but especially for outputting Javascript.

I sometimes revert to double quotes if I know a string will contain a lot of PHP variables, but to be honest it is quite rare.

There are only three reasons one should ever be using double quotes in PHP for strings – you want white-space collapsing because you’re sending it over a network socket to a SQL engine, when you want to use inlined variables because you’re TOO LAZY to type two to four extra characters (lame), or finally when you want certain escape codes that don’t work in single quotes like /n or /t… Of course with single quotes PRESERVING white-space … Ok, so only one legitimate reason, the white-space compressing for SQL.

Double quotes are slower due to the more complex parsing engine, mean you have to either escape or use the wrong quotes in you output, and on the whole are as responsible for sloppy half-assed code as putting <?php ?> on every line, or ALWAYS using string addition on echo instead of comma delimited output.

So part from building query strings, I’m with ScallioXTX on it too.

But then, I learned machine language first, then Wirth family languages BEFORE I learned C family, so things like variable parsing inside strings or idiocy like heredoc has never made any sense to me – ESPECIALLY in INTERPRETED languages.

I can find no reference in the PHP manual to the collapsing whitespace feature - nor do double strings collapse whitespace in my experience. Can you provide an example, or better yet, a link to the fine manual which explains the collapsing whitespace feature.

Thanks.

I just tested and yer right… so there’s literally NO good reason to use them in PHP… Stick double quotes in the same box as <?php ?> then, they should be removed entirely from the language as a waste of code, overhead and promoting bad coding practices.

Wonder where it was that did that then… C? JS? (no, JS throws an error on carriage returns)… Perl? Gah, I’m switching languages too often these days, I’m getting them all confused.

What I get the past week coding 8088 Assembly language again… My bad.

Just doing a quick test using:


<?php

/**
 * String Parsing - Measuring of Time Taken
 */
 
$answer = 'Unknown';

function gentime() {
  static $a;
  if($a == 0) $a = microtime(true);
  else return (string)(microtime(true)-$a);
}

gentime(); // Start timing
echo "<p>The answer is $answer</p>";
$time_taken['double_quotes'] = gentime();

gentime(); // Start timing
echo '<p>The answer is '.$answer.'</p>';
$time_taken['single_quotes'] = gentime();


gentime(); // Start timing
echo <<<EOT
<p>The answer is $answer</p>
EOT;
$time_taken['heredoc'] = gentime();

echo '<pre>';
var_dump($time_taken);
echo '</pre>';
?>

It gives times taken:

  • Double Quotes: 6.1988830566406E-6 (0.0000071525573730469 Seconds)
  • Single Quotes: 2.0027160644531E-5 (0.000024080276489258 Seconds)
  • Heredoc: 2.598762512207E-5 (0.000030040740966797 Seconds)

Even the slowest is more then quick enough that the time taken should not matter from a parsing time point of view which one you use.

From a readability point of view I prefer double quotes as if a string has got to have a number of variables in concatenating them can look a bit messy

These are very interesting points of view. I wasn’t aware of heredoc. I looked it up, and there new "x"doc (like nowdoc) features in php 5.3. It looks like most are going for single quotes for a variety of reasons, but according to SpacePhoenix’s test, double quotes are faster (it looks minute, but it is good to know).

Your test is flawed in many ways…

  1. microtime has a actual linear resolution of 18.2ms in most implementations (SOME implementations run higher, but updating the timer takes away from execution time so…), so any number smaller than that is meaningless gibberish and probably more rounding error than fact.

  2. you didn’t turn on buffering, so network speed is effecting your numbers.

  3. you aren’t doing enough iterations to get a meaningful value.

  4. iterations means taking the part we’re actually testing OUT of the equation.

  5. You’re using string addition on the single quote version, unfairly penalizing it… that’s something to test for too.

So… we need to loop for a specified TIME PERIOD, using buffered output, clearing the buffer between each, testing against a fixed multiple of 18.2 times a second, with a comparison against loop without an echo inside it so as to isolate just the echo statement.

Thankfully I wrote an object a few months ago to handle just this type of testing.


<?php

class benchMarkTimer {
private
	$endTime,
	$count;
	
	function start() {
		/* turn on buffering to remove network from equation */
		ob_start();
		$this->count=0;
		/*
			wait for timer rollover so as to remove granularity skew
			run for 3.64 seconds to account for 18.2ms hardware granularity
		*/
		$this->endTime=microtime(true);
		while ($this->endTime==microtime(true)) {}
		$this->endTime=microtime(true)+3.64;
	}
	
	function notDone() {
		$this->count++;
		return microtime(true)<$this->endTime;
	}
	
	function done() {
		/* 
			clean and flush buffer when done so size of
			buffer doesn't skew numbers!
		*/
		ob_end_clean();
		return $this->count;
	}
}

$answer = 'Unknown';

$benchMark=new benchMarkTimer;

$benchMark->start();
while ($benchMark->notDone()) {}
$timeTaken['No Echo']=$benchMark->done();

$benchMark->start();
while ($benchMark->notDone()) {
	echo "<p>The answer is $answer</p>";
}
$timeTaken['Double Quotes']=$benchMark->done();

$benchMark->start();
while ($benchMark->notDone()) {
	echo '<p>The answer is ',$answer,'</p>';
}
$timeTaken['Single Quotes Delimited']=$benchMark->done();

$benchMark->start();
while ($benchMark->notDone()) {
	echo '<p>The answer is '.$answer.'</p>';
}
$timeTaken['Single Quotes String Add']=$benchMark->done();

$benchMark->start();
while ($benchMark->notDone()) {
	echo <<<EOT
<p>The answer is $answer</p>
EOT;
}
$timeTaken['heredoc']=$benchMark->done();

$benchMark->start();
while ($benchMark->notDone()) {
?><p>The answer is <?php echo $answer; ?></p>
<?php
}
$timeTaken['<?php ?>']=$benchMark->done();

echo '
<style type="text/css">
td,th {
	text-align:left;
	padding-right:2em;
	font-size:12px;
	line-height:14px;
	font-family:arial,sans-serif;
}
</style>
<table>
	<thead>
		<tr>
			<th>Test</th>
			<th>Iterations</th>
			<th>Time per iteration</th>
			<th>Adjusted for No Echo</th>
			<th>Percent compared to SQD</th>
		</tr>
	</thead><tbody>';
	
$noEchoTime=3.64/$timeTaken['No Echo'];
$singleDelimitedTime=3.64/$timeTaken['Single Quotes Delimited']-$noEchoTime;
	
foreach ($timeTaken as $name => $value) {
	$timePer=3.64/$value;
	echo '
		<tr>
			<th>',$name,'</th>
			<td>',$value,'</td>
			<td>',number_format($timePer,10),'</td>
			<td>',number_format($timePer-$noEchoTime,10),'</td>
			<td>',(
				$name=='No Echo' ? '' : number_format(
					100*($singleDelimitedTime/($timePer-$noEchoTime))
				,4).'%'
			),'
		</tr>';
}
echo '
	</tbody>
</table>';

?>

Which locally under a throttled and isolated VM returned this for me:


(higher is better on that last column)

Over six percent difference in speed per call just by using single quotes and commas over double quotes with inline vars?.. much less those numbers don’t even take into account the difference in the byte-code compiler? That’s actually what’s funny – we really SHOULDN’T see a difference execution side in the interpreter since the bytecode compiler SHOULD have taken care of that… which is where the real difference would be and why things like APC or Memcached are so effective.

Six percent to just hit a different key while typing sounds worth it to me – but maybe I’ve got my head wedged up 1982’s backside a bit given my current projects.

It’s interesting too the difference in comma delimited vs. string additon for echo… using string addition with echo is also slower… and unpredictable in results since, well as came up recently in another thread…


function test() {
  echo 'test';
}

echo 'this is a '.test();
echo 'this is a ',test();

outputs:
testthis is a
this is a test

as the function runs during the string addition BEFORE the value is sent to echo. It also means higher memory use which is why string additions should be reserved for when you have to use them – like inside inlined evaluations.

Benchmarking PHP performance is tricky – you don’t have access to accurate timers, there are factors you can’t even account for like code to bytecode time, bytecode caching, result caching, buffering, network performance during output… It’s why waiting for the timer to rollover, then running your routine flat out while waiting on a fixed period, said period a multiple of the hardware timer granularity is usually your best bet… Bigger your sample pool (over a million results per in this case) the more you can dial in the result.

… and it’s why microtime is a joke on anything that takes less than around two seconds to run, and can be off by as much of a 18th of a second.

imv it’s a “who cares” exercise because a few % of next to nothing is still next to nothing and not worth worrying about :), at least for me :wink:

I prefer to not use double quotes only because of readability not because of gaining a few milli, micro or nano seconds of processing time.

In terms of performance unless your code is doing 1000’s if not millions of calculations, whether you use single or double quotes won’t matter a razoo.

Like say… a hundred or so echo/strings per user call and several hundred thousand page-views per day? Like say… the average forums.

Be wary of saying “it’s only x%” - because you do that over enough things, suddenly you’re at 100%. See how people misinterpret the meaning of browser share.

Another ‘flaw’ in the testing occurred to me - we’re testing a relatively short string… take the massive echo from like… a template header; with multiple variables and inlined conditionals.

I took the output of my theme_header function from one of my CMS and gutted out the fancier logic:


	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
	xmlns="http://www.w3.org/1999/xhtml"
	lang="en"
	xml:lang="en"
><head>

<meta
	http-equiv="Content-Type"
	content="text/html; charset=utf-8"
/>
	
<link
	type="text/css"
	rel="stylesheet"
	href="',$urlRoot,'theme/screen.css"
	media="screen,projection,tv"
/>
	
<title>
	',$pageTitle,(
		empty($siteTitle) ? '' : ' - '.$siteTitle
	),'
</title>

</head><body>

<div id="pageWrapper">
	<h1>
		<a href="',$urlRoot,'">
			',$siteTitle,'
			<span></span><b></b>
		</a>
	</h1><hr />
';

plugged in all the variables and ran it for the normal echo, and the double quote… the numbers start to get interesting… as with the longer and more complex data, the double quote ran 80,467 iterations and single quotes managed 111,783 – that’s 39% more loops in the same amount of time. (so many I wonder if maybe I broke something – it shouldn’t be THAT many more!)

Like anything else, change one value, the whole thing goes funny… comparing a twenty character string to a complex output? World of difference.

Quantify “enough things”.

Even if you look at the differences between any of your “Time per Iteration” data to compare any 2 tests, the number of iterations per second would need to be in the 10’s of millions before noticing any performance difference

Like I said, a few % of next to nothing is still next to nothing and so you won’t notice any performance difference unless you’re doing an unusually large number of echos per second.

Well… singles vs. doubles, multiple <?php ?> per file, multiple parsed literals per string, passing values on every call procedurally instead of namespacing them with objects, putting all values globally so there’s no cascade to the namespace, manually using strings to store output as it’s built instead of using ob_start… (or in combination with)… Slapping excess classes on elements for no good reason and using presentational markup… using includes for logic flow instead of functions, The list of nonsensical choices you see in every-day code, that each on their own seems harmless and innocuous – until you realize that suddenly the code is 30-50% slower from ignoring what programmers have said are bad coding practice since the 60’s.

But of course people want to just sleaze out their stuff any old way – See the completely idiotic codebase that makes up Turdpress for examples of this in action.

In a lot of ways it’s aggravating, depressing, and really pathetically sad to see people making the same mistakes over and over again every five to eight years… mostly justified by lame excuses like “I don’t like how it looks” or “It takes longer” – the latter of those being the real laugh when the time spent typing in the handful of extra characters is usually more than saved when something goes awry – you see that with code formatting all the blasted time.

Like the “It’s formatted in the PHP, who cares about the output” nonsense.

The op in this case is only concerned with comparing single and double quotes in echo statements.

But even if you take into account other ways of optimising code for performance, I suspect you would still need “iterations” in at least the millions if not higher order of millions before noticing any difference by the “naked eye”.

So as I mentioned before, even using your “Time per Iteration” data, you would need iterations in the order of 10’s of millions before noticing any performance difference.

DS, just running that benchmark, for 3 different time, i get:

[TABLE]
[TR]
Test Iterations Time per iteration Adjusted for No Echo Percent compared to SQD [/TR]
[TR]
No Echo [TD]1448547[/TD]
[TD]0.0000025129[/TD]
[TD]0.0000000000[/TD]
[TD]
[/TD]
[/TR]
[TR]
Double Quotes [TD]932870[/TD]
[TD]0.0000039019[/TD]
[TD]0.0000013891[/TD]
[TD]95.2375% [/TD]
[/TR]
[TR]
Single Quotes Delimited [TD]948959[/TD]
[TD]0.0000038358[/TD]
[TD]0.0000013229[/TD]
[TD]100.0000% [/TD]
[/TR]
[TR]
Single Quotes String Add [TD]941041[/TD]
[TD]0.0000038681[/TD]
[TD]0.0000013552[/TD]
[TD]97.6185% [/TD]
[/TR]
[TR]
heredoc [TD]928564[/TD]
[TD]0.0000039200[/TD]
[TD]0.0000014072[/TD]
[TD]94.0129% [/TD]
[/TR]
[TR]
<?php ?> [TD]917164[/TD]
[TD]0.0000039688[/TD]
[TD]0.0000014559[/TD]
[TD]90.8665% [/TD]
[/TR]
[/TABLE]

[TABLE]
[TR]
Test Iterations Time per iteration Adjusted for No Echo Percent compared to SQD [/TR]
[TR]
No Echo [TD]1461313[/TD]
[TD]0.0000024909[/TD]
[TD]0.0000000000[/TD]
[TD]
[/TD]
[/TR]
[TR]
Double Quotes [TD]935599[/TD]
[TD]0.0000038906[/TD]
[TD]0.0000013996[/TD]
[TD]94.3867% [/TD]
[/TR]
[TR]
Single Quotes Delimited [TD]954882[/TD]
[TD]0.0000038120[/TD]
[TD]0.0000013211[/TD]
[TD]100.0000% [/TD]
[/TR]
[TR]
Single Quotes String Add [TD]937732[/TD]
[TD]0.0000038817[/TD]
[TD]0.0000013908[/TD]
[TD]94.9873% [/TD]
[/TR]
[TR]
heredoc [TD]933459[/TD]
[TD]0.0000038995[/TD]
[TD]0.0000014086[/TD]
[TD]93.7890% [/TD]
[/TR]
[TR]
<?php ?>
[TD]920882[/TD]
[TD]0.0000039527[/TD]
[TD]0.0000014618[/TD]
[TD]90.3721% [/TD]
[/TR]
[/TABLE]

[TABLE]
[TR]
Test Iterations Time per iteration Adjusted for No Echo Percent compared to SQD [/TR]
[TR]
No Echo [TD]1460173[/TD]
[TD]0.0000024929[/TD]
[TD]0.0000000000[/TD]
[TD]
[/TD]
[/TR]
[TR]
Double Quotes [TD]935864[/TD]
[TD]0.0000038895[/TD]
[TD]0.0000013966[/TD]
[TD]94.4533% [/TD]
[/TR]
[TR]
Single Quotes Delimited [TD]954882[/TD]
[TD]0.0000038120[/TD]
[TD]0.0000013191[/TD]
[TD]100.0000% [/TD]
[/TR]
[TR]
Single Quotes String Add [TD]945373[/TD]
[TD]0.0000038503[/TD]
[TD]0.0000013575[/TD]
[TD]97.1754% [/TD]
[/TR]
[TR]
heredoc [TD]941014[/TD]
[TD]0.0000038682[/TD]
[TD]0.0000013753[/TD]
[TD]95.9152% [/TD]
[/TR]
[TR]
<?php ?> [TD]926039[/TD]
[TD]0.0000039307[/TD]
[TD]0.0000014379[/TD]
[TD]91.7426% [/TD]
[/TR]
[/TABLE]

The order is the same for SQD and SQSA but for the rest the order was different. That was with PHP version 5.3.0

So using DS’s data and comparing SQD with DQ I get a time difference of

0.0000013702 - 0.0000012848 = 8.54E-8 per iteration.

That means that for 10 million iterations the time difference is a measly 0.854 secs.

For 20 million iterations the time difference is still only 1.71 secs.

I didn’t know the issue of quotes can be so hot and important for some people! :smiley: I’d say I mostly disagree with most of the opinions so far and I find double quotes very useful so that I use them most of the time. I use single quotes only when I’m sure I will not need to insert some variable into the string - for example associative array indexes, constant names in define(), etc. For all other purposes, especially if the string is long, I use double quotes by default. My reasons:

  • I can easily use escape characters like
    \r \
  • I can insert variables directly or expression in {} braces and it’s more readable to me than concatenating with .

Because I never know if I might need to use one of the above features I like to have double quotes because when the need arises I don’t need to change single quotes to double (this has happened to me a few times).

I don’t understand why some people find double quotes unreadable. To me using variables directly in strings is much more readable than using single quotes and concatenating. And I don’t think the speed differences are anything to worry about and if someone uses an opcode cache it becomes irrelevant.

And lastly, I don’t think this is an important issue and I don’t find it bad or ugly if someone uses single quotes. It’s a minor stylistic difference and not really anything to worry about. Let anyone use what they prefer. However, it’s important to know the differences.