tags:

views:

445

answers:

5

I recently looked at my source code and it was a real mess.

my php source:

echo '<h1>Rar<h1>';
echo '<span>Rar</span>';
echo '<p>Rar</p>';

and when I view the browser source for the page rendered:

<h1>Rar</h1><span>Rar</span><p>Rar</p>

is there a way for me to override echo so that every output would end with a newline, something like

function echo($string)
{
 echo $string . "\r\n";
}
+5  A: 

echo is not a function, but a language statement. It cannot be redefined. If you are looking to prettify your output markup, have look at Tidy.


What you could do, is use your IDE's search/replace method and replace all echo statements with echo PHP_EOL,. This would append the OS specific newline char(s) before any output. Note the comma after PHP_EOL as it is important.

You can output several values with echo like this:

echo 'one', $foo, PHP_EOL,
     'two', $bar, PHP_EOL;

so there is no need to write echo on each line.

However, I agree with anyone who suggested using a more dedicated approach to separate content and layout e.g. using template views or HereDoc.

In additon, there is very little gain in having pretty markup. If you are using tools like Firebug to inspect the HTML, you will have properly formatted markup regardless of the mess the markup really is. Moreover, on sites with a lot of visitors, you'll often find the markup minified, which is the opposite of what you are trying to do, simply because all these newlines and tabs add to the weight of the page, which leads to slower page loads and increased traffic cost.

Gordon
A: 

You can indirectly overload echo() by using the __toString() magic method like so:

<?php
class CleanOutput
{
    public $content;

    public function __construct($c) {
        $this->content= $c;
    }

    public function __toString() {
        return $this->content . '\r\n';
    }
}

$text= new CleanOutput('Hello world!');
echo $text;
?>

The above would output "Hello world!" with a newline and carriage return appended at the end. There's ways to further encapsulate this, but they are outside the scope of my answer.

Edit:
As was noted, the above solution is slow/clumsy. Here's a more elegant solution using output buffering:

<?
function clean_up($foo) {
   return $foo . '\r\n';
}
ob_start('clean_up');
ob_implicit_flush(true);
echo "Hello world!";
?>

This is faster and cleaner (although it technically doesn't 'override' echo).

David Titarenco
Absolutely correct and ingenious solution. The problem is, the OP would need to wrap every piece of text he's currently `echoing` into `new CleanOutput()`, which misses the point of the question. ;-)
deceze
This is tremendously inefficient; it takes over ten times as long as an echo/print equivalent. Also, '\r\n' will not work as expected. It must be enclosed in double quotes.
Johannes Gorset
Very true (on both counts). OP asked if echo can be overridden. I showed that it can :P
David Titarenco
Technically this doesn't override `echo`. `__toString` will be used whenever the object is used in a string context. That's `echo`, but also `print` or `(string)` or `'foo' . $object`
Gordon
Good point Gordon. Added another more elegant solution into the mix.
David Titarenco
+3  A: 

You have various possibilities to output HTML.

You can use the heredoc syntax:

$html = <<<EOF
<h1>Rar<h1>
<span>Rar</span>
<p>Rar</p>
EOF
echo $hml;

Or (what is way better in my opinion), separate HTML from PHP. E.g. put all the PHP logic in the top of the file and the HTML after the PHP block:

<?php
   // all your PHP goes here
   $foo = 'bar'
?>
<!-- HTML comes here -->
<html>
  <body>
    <div>Hello <?php echo $foo; ?> </div>
  </body>
</html>

Variables can be printed as shown above. But these variables don't contain HTML.

When you have to output HTML based on a condition, you can use the alternative syntax for control statements:

<?php if($some_condition): ?>
    <h1>Rar<h1>
    <span>Rar</span>
    <p>Rar</p>
<?php endif ?>

This way it is also easier to debug your HTML as it is not only a PHP string.

Felix Kling
+1 for separating HTML and PHP
Niels Bom
A: 

Another solution would be to separate your code from your layouts by using a proper templating engine.

Srirangan
... which PHP already is on itself.
Gordon
you'll always have some php-code in your layout
Natrium
@Gordon, I agree. PHP can be used as a templating engine. But it is not always used as one. In those cases, having templates makes life simpler?@Natrium, not really. I love the way it is done in Google webapp and Django (both Python frameworks) and the same can be achieved in PHP using Smarty or similar frameworks.
Srirangan
@Srirangan Using a *template* is fine, but adding another template *engine* on top of PHP adds useless bloat to your app imho.
Gordon
@Gordon, fair enough.
Srirangan
@Gordon In general I agree, but having played with HAML lately I reserve an exception for when the template engine cuts your LOCs down by 50% while increasing readability and guarantee of validity. :)
deceze
@deceze and what about performance? Did it increase too? Also, did you consider the LOCs for the framework itself in your counting? If you want valid output guaranteed you could just use DOM for templating or transparently run the output through Tidy.
Gordon
@Gordon I don't see why the LOCs of the framework count, if it saves me a ton of typing. The "compiled" template files can also easily be cached; in production indefinitely so.
deceze
@deceze They count because they have to be executed at some point. They add cyclomatic complexity. You may have saved a couple hundred lines but the total LOCs are now likely a couple thousand more. The execution *likely* slows down your app. And caching is something you could have done with APC too. You also have to learn the templating syntax. And tbh, I find all this Ruby flavored syntax impossible to read. I mean, use it if you like it. But I'm content with what PHP provides out of the box :)
Gordon
@Gordon I find the average PHP/HTML hotchpotch to be far less readable than HAML, way too many pointy brackets. But to each his own. ;o)
deceze
@deceze right on :)
Gordon
+2  A: 

You can set up and output buffer and then run the buffer through htmltidy. The tidy extension even has a specific function for the purpose. Just call this before you start outputting your html:

ob_start('ob_tidyhandler');
troelskn