9

Given the HTML generated by my application.

function pagination(){
  echo "<ul>\n";

  for($i = 1; $i <= 10; $i++)
    echo "\t<li>...</li>\n";

  echo "</ul>\n";
}
?>
<div>
  <?php pagination(); ?>
</div>

If I add another container DIV, this doesn't produce correctly indented code.

Is there any solution for the function to somehow know how many \t 's or spaces to add, or somehow automatically indent the html?

filype
  • 8,034
  • 10
  • 40
  • 66
thelolcat
  • 10,995
  • 21
  • 60
  • 102
  • 3
    If this is output for your actual page, you *shouldn't* indent it. That's just more characters the user has to download. Firebug and other structure debugging tools will automatically do that for you when you inspect elements. – animuson Feb 29 '12 at 02:28
  • If you were to have sections as loaded views like a mvc pattern this would not be too bad as the views html would most likely be on first indent. also its prefered to use `PHP_EOL` instead of `\n` or `\r\n` then new lines are compat with all systems. – Lawrence Cherone Feb 29 '12 at 02:32
  • 1
    @Lawrence your MVC pater has absolutely nothing to do with this question – Your Common Sense Feb 29 '12 at 07:49

10 Answers10

13

Amazing question.

9 answers and 3 comments so far, and looks like nobody bothered to read the question body, but just repeated some gospel triggered by a keyword in the title - a most preferred manner to answer questions on the blessed site of stackoverflow.

Yet the question not that simple/one-layered.
I have to admit, it's ambiguous itself. So, we have to dig it out.

1) How do you indent your HTML?

Use templates, dude. Use templates. The only answer.

2) Is there any solution for the function to somehow know how many \t 's or spaces to add, or somehow automatically indent the html?

Of course there isn't.
PHP knows nothing of HTML, indents and such.
Especially when no HTML is ready yet(!)

3) If I add another container DIV, this doesn't produce correctly indented code.

The key question of the question.
The question for sake of which the question were asked.

Yet hardest of them all.

And the answer is kind of ones I showed total disagreement with, hehe:
Although relative order of tags is important, for the resulting large HTML it is possible to move some blocks out of row:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>Hello</h1>
    <div>
<!-- news list -->
<div>
  <ul>
    <li>1..</li>
    <li>2..</li>
    <li>3..</li>
    <li>4..</li>
  </ul>
</div>
<!-- /news list -->
    </div>
    <div>
<!-- pagination -->
<ul>
  <li>Red</li>
  <li>Green</li>
  <li>Blue</li>
  <li>Black</li>
</ul>
<!-- /pagination -->
    </div>
</body>
</html>

It will let you have proper indention in the meaningful blocks, yet keep the main HTML in order.
As a side effect it will keep your lines on the screen :)

To keep good indentation inside sub-templates, I'd strongly suggest using PHP-based templates. Not ugly HEREDOC for goodness' sake!
Here is only one rule to follow with PHP templates:
always keep PHP blocks to the left side. That's all.
To keep indentation between PHP nested blocks, just indent them inside <? ?>

Example:

<ul>
<? foreach ($thelist as $color): ?>
  <li>
<?   if ($color == $current): ?>
    <b><?=$color?></b>
<?   else ?>
    <a href="?color=<?=$color?>"><?=$color?></a>
<?   endif ?>
  </li>
<? endforeach ?>
</ul>

This will produce correctly indented HTML, while keeping order of both HTML and PHP in the template, making developer's life easer both at development and debugging.

Do not listen to anyone who says "no need to indent your code at all!". They are merely hobbyists, not the real developers. Anyone who have an idea of what debugging is, who had hard times debugging their code, would tell you that proper indentation is essential.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • I do use templates, but there are situations (like the pagination thing) where using templates is kind of stupid, because you have to do complicated stuff inside your template. See for example [this class](https://github.com/onassar/PHP-Pagination), which is basically useless, the render.inc does all the job that goes in the template... – thelolcat Feb 29 '12 at 14:15
  • You just taking templates wrong. Templates are definitely not to make things "simple" (not complicated). Templates are to separate data processing from data displaying. They can be comlicated as well but they have to be separated from the data processing. Any class mixing these matters is a rubbish. The point of my post was quite different though. – Your Common Sense Feb 29 '12 at 14:26
  • "Anyone who have an idea of what debugging is, who had hard times debugging their code, would tell you that proper indentation is essential." <- That's simply no longer true. There are several implementations of "View Source" that allow you to (re-)indent the code client-side. For this reason I now allow Railo to collapse all excess whitespace which reduces the amount of bytes to be sent. – SpliFF Mar 01 '12 at 00:34
  • @SpliFF all these implementations do *render* the code. This or that way they alter it. Some DOM changes, even attempts to correct wrong tags - the purpose of these viewers is different from debugging output - that's the problem. – Your Common Sense Mar 01 '12 at 04:03
3

The answer could sound weird, but you should not worry about the generated code's indentation. Indentation is for readability, and should be only of concern on the programmer's side, not on the generated part (which is for browsers).

Uku Loskit
  • 40,868
  • 9
  • 92
  • 93
  • Where I generally agree. I do often find it nice to have some pretty source. For the snoops that is. still +1 because it's the most sensible response. – rlemon Feb 29 '12 at 02:42
  • That's true. usual PHP user have no idea of HTML generated by their script and don't care. – Your Common Sense Feb 29 '12 at 05:11
  • 2
    I didn't but I want to -1. It doesn't answer the question at all. The OP wants to know how to indent generated HTML. Instead everyone keeps answering "You shouldn't" or "No Point". Well there is a point, that's what the OP wants. As for "formatted code is only for developers" how about a client looking at the source of there website, so see unreadable code? Not very professional. – Bradmage Apr 25 '12 at 08:24
1

I agree with all comments saying don't bother but if you do have a case where doing so makes sense then you can pipe your HTML through HTML Tidy (or in your case PHP Tidy) using the indent option.

SpliFF
  • 38,186
  • 16
  • 91
  • 120
0

Edit: broke the code down into pages.

This code really only works with a template system.
Which can just be a basic:

// file: index.tpl.html

<html>
    <head>
    </head>
    <body>
        <div>Some header code</div>
        <div>
            {mainContent}
        </div>
        <div>Some footer code</div>
    </body>
</html>

// file: functions.php
<?php
    function pagination()
    {
        $output = "<ul>\n";

        for($i = 1; $i <= 10; $i++)
            $output = "\t<li>...</li>\n";

        $output = "</ul>\n";

        return $output;
    }

    function indent_html($html, $tag, $new_html)
    {
        // magic indenting code: finds how many spaces are used on the line above it
        $spacePos = 0;
        $find  = strpos($html, '{'.$tag.'}' );
        while( $html[ $find-$spacePos-1] == ' ' ) $spacePos++;

        // Uses the indent from the line above to indent your new html
        return str_replace("\n", "\n".str_repeat(" ", $spacePos), $new_html);
    }
?>

// file: index.php
<?php
    $html = file_get_contents("index.tpl.html");

    // magic indenting code: finds how many spaces are used on the line above it
    $spacePos = 0;
    $find  = strpos($html, '{mainContent}' );
    while( $html[ $find-$spacePos-1] == ' ' ) $spacePos++;

    // your pagination() needs to return html not output it
    $mainContent = pagination();
    $mainContent = indent_html($html, $tag, $mainContent);

    // Uses the indent from the line above to indent your new html
    $mainContent = str_replace("\n", "\n".str_repeat(" ", $spacePos), $mainContent);

    // finally insert your html
    $html = str_replace("{mainContent}", $mainContent, $html);
?>

Might need some modification if you want to use tabs instead of spaces.
I use spaces as it's more cross browser/application.

Bradmage
  • 1,233
  • 1
  • 15
  • 41
  • what is the "template system" you are talking about? – Your Common Sense Apr 25 '12 at 10:31
  • Why the down vote? It answers the question, all generated code gets indented. and @YourCommonSense I was just showing how it can be used, `home/index.tpl.html` would contain `{mainContent}` which gets replaced with the generated code, and indented to the same level as the code surrounding it. – Bradmage Apr 26 '12 at 11:27
  • your solution use no tamplates. so, it shouldn't be used at all – Your Common Sense Apr 26 '12 at 11:38
  • A template is just a reusable file. It doesn't have to be called from a 2000 line class to be called a "template system". The fact the html page doesn't have any dynamic (php in this case) code in it, is enough to call it a template. – Bradmage Apr 26 '12 at 18:41
  • You just have no idea what a template is and *what it is used for.* There is no problem in having a dynamic code in the template. (Moreover, it's just impossible to avoid it!) But **to use templates you shouldn't have any static HTML in your PHP code either** – Your Common Sense Apr 27 '12 at 04:55
  • I think I provided a nice lightweight example of a template system. my answer wasn't showing template functionality, but where my indent solution would be positioned in the code. But I've noticed you just seem to be argumentative. So I'll just put it down to that. – Bradmage May 02 '12 at 08:19
  • it is not a "lightweight" template. Your terrific `$output = "\t
  • ...
  • \n";` is NOT A TEMPLATE AT ALL. Go figure. – Your Common Sense May 02 '12 at 08:20
  • yeah no shit, the function pagination() is from the question. index.tpl.html is the template. Don't comment on code that isn't mine. – Bradmage May 02 '12 at 10:00
  • it is yours. you are not using a template in your answer. so, your answer is just useless. – Your Common Sense May 02 '12 at 10:03
  • Well I am, I said that in my last comment, index.tpl.html is the template. And my index.php processes all the data and places it into index.tpl.html. Which makes it a template system. an no, if you look at the question, pagination() is the majority of the question, you can't miss it. Maybe you should go back to basics? Try http://en.wikipedia.org/wiki/Web_template – Bradmage May 02 '12 at 10:16
  • A silly html page doesn't make a template system, lol. One can say that they have a template system ONLY if they have their business logic FULLY separated from the presentation logic. While your index.php does process the data as well as design, mixing it and thus spoiling whole idea of templates. think of it. The page you linked to says plain nonsense. you cannot separate your content from design. – Your Common Sense May 02 '12 at 10:31
  • A template doesn't have anything to do with business logic. You can quite simply use php in it's basic form, and use $head_title $body_content to reuse a block of html (in this case index.tpl.html ) with no further logic than including aboutus.html, services.html which has the actual content. You talking about mixing data and design is getting into things like design patterns (like the all popular MVC). When talking about templates, it is literally a way not so have copied onto every page that gets called. – Bradmage May 02 '12 at 10:55
  • How about elaborating your idea of a template (if it's not a html file) instead of constantly telling me I'm wrong? That would be a lot more constructive. – Bradmage May 02 '12 at 10:55