15

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";
}
yretuta
  • 7,963
  • 17
  • 80
  • 151
  • 2
    and when you *dont't* want a newline? what would you do then? – grapefrukt Feb 02 '10 at 08:40
  • "and when you don't want a newline?" --- Use print? – PurplePilot Feb 02 '10 at 08:48
  • Related: http://stackoverflow.com/questions/948682/how-to-keep-php-view-source-html-output-clean/ – soulmerge Feb 02 '10 at 09:01
  • 5
    IMHO, HTML is for the browser to read, not for the human. As long as your source code is readable, I wouldn't worry about the HTML output. Clean HTML output is icing on the cake that's very hard to achieve in any moderately complex application without proper templating or tools like Tidy. – deceze Feb 02 '10 at 09:02
  • 1
    deceze is right, HTML is for the browser. If you want to view the HTML anyway, I recommend Firebug. Firebug gives you a complete fold-in fold-out view of your HTML and even updates it when it's altered by Javascript. _Very_ handy. – Niels Bom Feb 02 '10 at 09:08
  • True, but having a "normal" HTML file it is easier to edit and maintain if you have line breaks and indentation ;) – Felix Kling Feb 02 '10 at 09:18
  • Why would you edit and maintain an HTML file that is produced by a PHP script? – Niels Bom Feb 02 '10 at 09:19
  • @Niels Bom: Separation of PHP and HTML? If I have an array and loop through it to generate HTML, it is easier to work with the HTML inside the loop if it is proper formatted. Or is this not "generated" enough ;) – Felix Kling Feb 02 '10 at 09:22
  • @Felix No, that's not "generated" enough. :) That's still the source code level, and of course your HTML should be properly formatted there. Having the HTML still perfectly formatted *after* the loop is done is quite hard and not something worth worrying about. – deceze Feb 02 '10 at 09:40

6 Answers6

10

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
  • 312,688
  • 75
  • 539
  • 559
3

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
  • 795,719
  • 175
  • 1,089
  • 1,143
2

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
  • 115,121
  • 27
  • 131
  • 155
1

Although this solution does not override echo, you can get something close to echo with a newline. Add:

function e() {
    return o::singleton();
}

class o {
    private static $instance;

    public static function singleton()
    {
        if (!isset(self::$instance)) {
            $className = __CLASS__;
            self::$instance = new $className;
        }
        return self::$instance;
    }

    public function __set($prop, $txt) {
        echo $txt . PHP_EOL;
    }
}

to your file, and then you can use:

e()->o = "Line which ends in newline";

instead of echo.

torbenl
  • 296
  • 2
  • 6
0

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
  • 32,662
  • 13
  • 66
  • 111
  • 4
    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 Feb 02 '10 at 08:58
  • 2
    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 Feb 02 '10 at 09:03
  • Very true (on both counts). OP asked if echo can be overridden. I showed that it can :P – David Titarenco Feb 02 '10 at 09:07
  • 2
    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 Feb 02 '10 at 09:12
  • Good point Gordon. Added another more elegant solution into the mix. – David Titarenco Feb 02 '10 at 09:16
  • 1
    This second solution is pretty neat! Thank you! – OMA Jul 07 '17 at 12:40
0

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

Sri
  • 5,805
  • 10
  • 50
  • 68
  • @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. – Sri Feb 02 '10 at 11:39
  • 1
    @Srirangan Using a *template* is fine, but adding another template *engine* on top of PHP adds useless bloat to your app imho. – Gordon Feb 02 '10 at 11:51
  • @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 Feb 02 '10 at 12:47
  • @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 Feb 02 '10 at 13:26
  • @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 Feb 02 '10 at 14:30
  • @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 Feb 02 '10 at 14:45
  • @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 Feb 02 '10 at 14:59